1

I wanted to build a nested dictionary based on a text file. for example. (text.txt)

...
hostA           hostA.testing.com               192.168.1.101
hostB           hostB.testing.com               192.168.1.102
...

Ideally, I want to get the following nested dictionary

...
{'hostA': {'FQHN': 'hostA.testing.com', 'IP': '192.168.1.101'}, 'hostB': {'FQHN': 'hostB.testing.com', 'IP': '192.168.1.102'}}
...

So I made the following Python code:

myinnerdict={}
myouterdict={}

def main():
    my_fh = open('text.txt', 'r')
    for line in my_fh:
        newline = line.strip().split()    # get ride of the '\n' and make it a inner list .
        #print(newline)
        myinnerdict['FQHN']=newline[1]
        myinnerdict['IP']=newline[2]
        #print(myinnerdict)
        #print(newline[0])
        myouterdict[newline[0]]=myinnerdict
    print(myouterdict)

if __name__ == "__main__":
    main()
...

however, beyond my understanding , when I ran it I got this result:

...
{'hostA': {'FQHN': 'hostB.testing.com', 'IP': '192.168.1.102'}, 'hostB': {'FQHN': 'hostB.testing.com', 'IP': '192.168.1.102'}}
...

which is not what I wanted , I don't know what I missed, please kindly help.

Moon Cheesez
  • 2,489
  • 3
  • 24
  • 38
Eric Zhang
  • 13
  • 5

2 Answers2

1

This is happening because you are reusing the same dict object for the innerdict. You need create a new dict object within your loop:

myouterdict={}

def main():
    my_fh = open('text.txt', 'r')
    for line in my_fh:
        myinnerdict={}
        newline = line.strip().split()    # get ride of the '\n' and make it a inner list .
        #print(newline)
        myinnerdict['FQHN']=newline[1]
        myinnerdict['IP']=newline[2]
        #print(myinnerdict)
        #print(newline[0])
        myouterdict[newline[0]]=myinnerdict
    print(myouterdict)

if __name__ == "__main__":
    main()
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
0

The problem is that you are reusing the same variable for the dictionary. As myouterdict is storing the reference to the variable myinnerdict instead of the actual data, therefore, both of them are the same. For example, try this:

>>> a = {}
>>> b = {"my a variable": a}
>>> b
{'my a variable': {}}
>>> a["asdf"] = 3
>>> b
{'my a variable': {'asdf': 3}}

As you can see, b is storing the reference of a and not the empty dict data of a. What you need to do is .copy() it over (Note that .copy() does not copy the contents of the dict but makes a new reference read more here):

myinnerdict = {}
myouterdict = {}

def main():
    my_fh = open('text.txt', 'r')
    for line in my_fh:
        newline = line.strip().split()

        myinnerdict['FQHN'] = newline[1]
        myinnerdict['IP'] = newline[2]
        # Note this copy here
        myouterdict[newline[0]] = myinnerdict.copy()
    print(myouterdict)
    # Remember to close the file!
    my_fh.close()

if __name__ == "__main__":
    main()

Anyways, you could also just immediately assign a newly created dict object instead of using a variable:

mydict = {}

def main():
    my_fh = open('test.txt', 'r')
    for line in my_fh:
        newline = line.strip().split()
        mydict[newline[0]] = {"FQHN": newline[1], "IP": newline[2]}
    print(mydict)
    my_fh.close()

if __name__ == "__main__":
    main()
Community
  • 1
  • 1
Moon Cheesez
  • 2,489
  • 3
  • 24
  • 38