Python Forum

Full Version: how to create a nested dict..
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
its me again, i guess i will never get my head around this language.

i have the following code..

def get_niminfo(self):
        file = '/etc/niminfo'
        niminfo = {}
        niminfo = niminfo['niminfo'] = {}

        try:
            if os.path.exists(file):
                niminfo = dict(
                    (k.strip(), v.strip(' "\n')) for k, v in (
                        line.split(
                            ' ', 1)[1].split(
                                '=', 1) for line in (
                                    (l for l in open(
                                        file, 'r') if l.startswith('export'))) if not re.match(
                                            r'^\s*$', line)))
        except IOError as e:
            module.warnings.append('could not read /etc/niminfo')
            niminfo = {}
        return niminfo
it returns the following (ignore the "ansible_" prefix)...

"ansible_facts": {
        "ansible_NIM_BOSINST_DATA": "/NIM_BOSINST_DATA",
        "ansible_NIM_BOSINST_RECOVER": "/../SPOT/usr/lpp/bos.sysmgt/nim/methods/c_bosinst_env -a hostname=host1",
        "ansible_NIM_BOS_FORMAT": "mksysb",
        "ansible_NIM_BOS_IMAGE": "/NIM_BOS_IMAGE",
        "ansible_NIM_CONFIGURATION": "standalone",
        "ansible_NIM_CUSTOM": "/../SPOT/usr/lpp/bos.sysmgt/nim/methods/c_script -a location=nimserver:/export/nim/scripts/host1.script",
        "ansible_NIM_FIPS_MODE": "0",
        "ansible_NIM_HOSTNAME": "host1",
        "ansible_NIM_HOSTS": "127.0.0.1:loopback:localhost  10.0.0.1:host1  10.0.0.2:nimserver",
        "ansible_NIM_LICENSE_ACCEPT": "yes",
        "ansible_NIM_MASTERID": "00F7089898989",
        "ansible_NIM_MASTER_HOSTNAME": "nimserver",
        "ansible_NIM_MASTER_PORT": "1058",
        "ansible_NIM_MOUNTS": "nimserver:/export/lpp_source/aix72/7200-00-02-1614:/SPOT/usr/sys/inst.images:dir  nimserver:/export/nim/niminstall/bosinstdata/bos_wop_mirror:/NIM_BOSINST_DATA:file  nimserver:/export/mksysb/mksysb_master_aix72_00:/NIM_BOS_IMAGE:file",
        "ansible_NIM_NAME": "host1",
        "ansible_NIM_REGISTRATION_PORT": "1059",
        "ansible_NIM_SHELL": "shell",
        "ansible_RC_CONFIG": "rc.bos_inst",
        "ansible_SPOT": "nimserver:/export/spot/spot_aix72_00/spot_aix72_00/usr", }
but my intention was this

"niminfo": {
        "NIM_BOSINST_DATA": "/NIM_BOSINST_DATA",
        "NIM_BOSINST_RECOVER": "/../SPOT/usr/lpp/bos.sysmgt/nim/methods/c_bosinst_env -a hostname=host1",
        "NIM_BOS_FORMAT": "mksysb",
        "NIM_BOS_IMAGE": "/NIM_BOS_IMAGE",
        "NIM_CONFIGURATION": "standalone",
        "NIM_CUSTOM": "/../SPOT/usr/lpp/bos.sysmgt/nim/methods/c_script -a location=nimserver:/export/nim/scripts/host1.script",
        "NIM_FIPS_MODE": "0",
        "NIM_HOSTNAME": "host1",
        "NIM_HOSTS": "127.0.0.1:loopback:localhost  10.0.0.1:host1  10.0.0.2:nimserver",
        "NIM_LICENSE_ACCEPT": "yes",
        "NIM_MASTERID": "00F7089898989",
        "NIM_MASTER_HOSTNAME": "nimserver",
        "NIM_MASTER_PORT": "1058",
        "NIM_MOUNTS": "nimserver:/export/lpp_source/aix72/7200-00-02-1614:/SPOT/usr/sys/inst.images:dir  nimserver:/export/nim/niminstall/bosinstdata/bos_wop_mirror:/NIM_BOSINST_DATA:file  nimserver:/export/mksysb/mksysb_master_aix72_00:/NIM_BOS_IMAGE:file",
        "NIM_NAME": "host1",
        "NIM_REGISTRATION_PORT": "1059",
        "NIM_SHELL": "shell",
        "RC_CONFIG": "rc.bos_inst",
        "SPOT": "nimserver:/export/spot/spot_aix72_00/spot_aix72_00/usr", }
so how to get the additional dict level in?
mydict = {
    'Boston': {
        'Resturants': {
            'Spoke Wine Bar': {
                'Addr1': '89 Holland St',
                'City': 'Sommerville',
                'ZipCode': '02144',
                'Phone': '617-718-9463'
            },
            'Highland Kitchen': {
                'Addr1': '150 Highland Ave',
                'City': 'Sommerville',
                'ZipCode': '02144',
                'Phone': '617-625-1131'
            }
        },
        'Hotels': {
            ....
        }
    }
}
ah, ok...but i have no clue how to implement this in my code...
wardancer84 Wrote:it returns the following (ignore the "ansible_" prefix)...
It can't return what you said, because your result is not a python object, neither is your expected output. It makes the question impossible to answer.

If you've read "the zen of python", you know that
Tim Peters Wrote:Beautiful is better than ugly.
That's why we try to avoid very long and obfuscated list comprehensions. The code would be better with line 8-15 split in several steps.
hmm..ok. will try my luck at another place.
Here's how you can build a dictionary on the fly:

#  Author: Larz60+ Nov 22, 2018
import os


class CreateDict:
    def __init__(self):
        os.chdir(os.path.abspath(os.path.dirname(__file__)))

    def new_dict(self, dictname):
        setattr(self, dictname, {})

    def add_node(self, parent, nodename):
        node = parent[nodename] = {}
        return node
    
    def add_cell(self, nodename, cellname, value):
        cell =  nodename[cellname] = value
        return cell

    def display_dict(self, dictname, level=0):
        indent = " " * (4 * level)
        for key, value in dictname.items():
            if isinstance(value, dict):
                print(f'\n{indent}{key}')
                level += 1
                self.display_dict(value, level)
            else:
                print(f'{indent}{key}: {value}')
            if level > 0:
                level -= 1


def testit():
    cd = CreateDict()
    cd.new_dict('CityList')
    boston = cd.add_node(cd.CityList, 'Boston')
    bos_resturants = cd.add_node(boston, 'Resturants')
    spoke = cd.add_node(bos_resturants, 'Spoke Wine Bar')
    cd.add_cell(spoke, 'Addr1', '89 Holland St')
    cd.add_cell(spoke, 'City', 'Sommerville')
    cd.add_cell(spoke, 'Addr1', '02144')
    cd.add_cell(spoke, 'Phone', '617-718-9463')

    highland = cd.add_node(bos_resturants, 'Highland Kitchen')
    cd.add_cell(highland, 'Addr1', '150 Highland Ave')
    cd.add_cell(highland, 'City', 'Sommerville')
    cd.add_cell(highland, 'ZipCode', '02144')
    cd.add_cell(highland, 'Phone', '617-625-1131')

    print(f'\nCityList Dictionary')
    cd.display_dict(cd.CityList)
    print(f'\nraw data: {cd.CityList}')

if __name__ == '__main__':
    testit()
The test routing has the code to reproduce the sample dictionary I show above in post #2
Output:
Boston Resturants Spoke Wine Bar Addr1: 02144 City: Sommerville Phone: 617-718-9463 Highland Kitchen Addr1: 150 Highland Ave City: Sommerville ZipCode: 02144 Phone: 617-625-1131 raw data: {'Boston': {'Resturants': {'Spoke Wine Bar': {'Addr1': '02144', 'City': 'Sommerville', 'Phone': '617-718-9463'}, 'Highland Kitchen': {'Addr1': '150 Highland Ave', 'City': 'Sommerville', 'ZipCode': '02144', 'Phone': '617-625-1131'}}}}