pslover
pslover

Reputation: 72

how to read json embedded ini config file in python

I'm using python 3.4 I have problem reading config file having json format in formatted way(i.e. not in same line.) my config file 'Example.config' goes like this

[ABC]

outdoor = {'GAME':['cricket',
                    'football'],
           'INFO':[
                      {'Players':'eleven',
                       'Fun':'Unlimited'},
                      {'Players':'something',
                       'Fun':'Much_more'}
                     ]
         }

[XYZ]

INDOOR = {'GAME':['Carom'],
           'INFO':[
                        {'Players':'2','Fun':'Less'},
                        {'Players':'4','Fun':'More'}
                      ]
          }

INDOOR1 = {'GAME':['TABLE-TENNIS',
                    'BASKETBALL',
                    'ANYTHING'],
          'INFO':[
                    {'Players':'TWO','Fun':'MORE'},
                    {'Players':'MORE','Fun':'MUCHMORE'}
                     ]
         }

mycode

config_parser=ConfigParser()
    config_parser.read('Example.config')
    for each_section in config_parser.sections():
        for option in config_parser.options(each_section):
            option=ast.literal_eval(option)
            try:
                games=option['GAME']
                info=option['INFO']
            except:
                print('PLease format config same as qa_config.config file.Please Pay special attention to casing')
                raise

            for game in games:
                for eachInfo in info:
                    _INFO=eachInfo['Players']
                    _FUN=eachInfo['Fun']
                    print (each_section,':\n')
                    print ('\t',game,':\n')
                    print ('\t',_INFO,':\n')
                    print ('\t',_FUN,':\n')

Error :

option=ast.literal_eval(option)
  File "C:\Python34\lib\ast.py", line 84, in literal_eval
    return _convert(node_or_string)
  File "C:\Python34\lib\ast.py", line 83, in _convert
    raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.Name object at 0x02E61910>

If I keep dictionary in one line as string without any beautification in config file ast.literal_eval() is able to handle it.

For example:

outdoor = {'GAME':['cricket','football'],'INFO':[{'Players':'eleven','Fun':'Unlimited'},{'Players':'something','Fun':'Much_more'}]}

So I guess this is due to tabs and spaces I'm using in config file. But I need beautification in config file as user will update it.

I've also tried with asteval and json.load. T.I.A.

Upvotes: 1

Views: 3410

Answers (2)

meuh
meuh

Reputation: 12255

I tried your code and example (admittedly in 2.7) and the problem was that you are using ast.literal_eval() on the wrong thing.

You are using it on option which is the name on the left-hand side of the ini file (in your example the words outdoor, INDOOR and INDOOR1). You want to use it on the right-hand side value of this option.

Add the missing 2nd line below to the appropriate loop in your script:

    for option in config_parser.options(each_section):
        option = config_parser.get(each_section, option)
        option = ast.literal_eval(option)

Your multiline ini file is perfectly parsed.

Upvotes: 2

larsks
larsks

Reputation: 312868

As you've discovered, that's not valid INI syntax. If you really require that sort of deeply structured data, consider just using YAML for your configuration file, which would look like this:

ABC:
  outdoor:
    GAME:
       - cricket
       - football
    INFO:
      - Players: eleven
        Fun: unlimited
      - Players: something
        Fun: much more

And parse like this:

>>> import yaml
>>> with open('myconfig.yml') as fd:
...   config = yaml.load(fd)

Which as you can see parses directly into Python data structures:

>>> import pprint
>>> pprint.pprint(config)
{'ABC': {'outdoor': {'GAME': ['cricket', 'football'],
                     'INFO': [{'Fun': 'unlimited', 'Players': 'eleven'},
                              {'Fun': 'much more', 'Players': 'something'}]}}}

Upvotes: 0

Related Questions