Reputation: 72
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
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
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