问题
I'm using the configparser library in python to manage my configuration files.
But, I can't find a method to store and retrieve tuples data-structure through it.
My data is a dictionary of tuples.
name_mapper = {
0 = (0, 0)
1 = (0, 1)
2 = (0, 2)
3 = (1, 0)
4 = (1, 1)
5 = (1, 2)
6 = (2, 0)
7 = (2, 1)
8 = (2, 2)
9 = (3, 0)
10 = (3, 1)
11 = (3, 2)
}
When I write this dictionary via configparser, everything becomes a string.
myconfig.ini
[NAME_MAPPER]
0 = (0, 0)
1 = (0, 1)
2 = (0, 2)
3 = (1, 0)
4 = (1, 1)
5 = (1, 2)
6 = (2, 0)
7 = (2, 1)
8 = (2, 2)
9 = (3, 0)
10 = (3, 1)
11 = (3, 2)
Now, on reading the "my_config.ini"
config = configparser.ConfigParser()
config.read('config_params.ini')
name_mapper = dict(config['NAME_MAPPER'])
But, the dictionary no longer holds tuples, its just tuple formatted as string.
name_mapper = {
'0' = '(0, 0)'
'1' = '(0, 1)'
'2' = '(0, 2)'
'3' = '(1, 0)'
'4' = '(1, 1)'
'5' = '(1, 2)'
'6' = '(2, 0)'
'7' = '(2, 1)'
'8' = '(2, 2)'
'9' = '(3, 0)'
'10' = '(3, 1)'
'11' = '(3, 2)'
}
I figured out a way to correct this by using ast.literal_eval method.
from ast import literal_eval
new_name_mapper = dict()
for each in name_mapper:
new_name_mapper[int(each)] = literal_eval(name_mapper[each])
Now, new_name_mapper is correctly formatted.
name_mapper = {
0 = (0, 0)
1 = (0, 1)
2 = (0, 2)
3 = (1, 0)
4 = (1, 1)
5 = (1, 2)
6 = (2, 0)
7 = (2, 1)
8 = (2, 2)
9 = (3, 0)
10 = (3, 1)
11 = (3, 2)
}
But I'm sure, its not the best approach. Anyone got better & more pythonic ideas.
回答1:
Config parser will always return Strings, except you use an explicit converter using the getbool
getint`` etc methods. However you can write your own converter function and register it with your parser, then use it to retrieve the value any way you like.
From the Configparser Docs:
converters, default value: not set
Config parsers provide option value getters that perform type conversion. By default getint(), getfloat(), and getboolean() are implemented. Should other getters be desirable, users may define them in a subclass or pass a dictionary where each key is a name of the converter and each value is a callable implementing said conversion. For instance, passing {'decimal': decimal.Decimal} would add getdecimal() on both the parser object and all section proxies. In other words, it will be possible to write both parser_instance.getdecimal('section', 'key', fallback=0) and parser_instance['section'].getdecimal('key', 0).
If the converter needs to access the state of the parser, it can be implemented as a method on a config parser subclass. If the name of this method starts with get, it will be available on all section proxies, in the dict-compatible form (see the getdecimal() example above).
So you could write a function to parse the tuple
>>> def parse_tuple(input):
... return tuple(k.strip() for k in input[1:-1].split(','))
>>> parse_tuple('(1, 2, 3)')
>>> ('1', '2', '3')
or if you want ints:
>>> def parse_int_tuple(input):
... return tuple(int(k.strip()) for k in input[1:-1].split(','))
>>> parse_int_tuple('(1, 2, 3)')
>>> (1, 2, 3)
the create your configparser object, passing this converter:
>>> parser = ConfigParser(converters={'tuple': parse_int_tuple})
>>> parser.read_dict({'NAME_MAPPER': name_mapper})
>>> parser['NAME_MAPPER'].gettuple('0')
(0, 0)
IMO this is the most pythonic approach since it uses only well documented functionality
来源:https://stackoverflow.com/questions/56967754/how-to-store-and-retrieve-a-dictionary-of-tuples-in-config-parser-python