问题
I'm using the Python configparser to generate config.ini
files to store my scripts configuration. The config is generated by code, but the point of the file is, to have an external way to change the programmatically generated config at later stages. So the file needs to be well readable and config options should be easy to find. The sections in configparser are a nice way to ensure that, however within a section, the entries seem to be ordered randomly. For example this code:
import configparser
config = configparser.ConfigParser()
config['DEFAULT'] = {
'shuffle': 'True',
'augment': 'True',
# [... some other options ...]
'data_layer_type' : 'hdf5',
'shape_img' : '[1024, 1024, 4]',
'shape_label' : '[1024, 1024, 1]',
'shape_weights' : '[1024, 1024, 1]'
}
with open('config.ini', 'w') as configfile:
config.write(configfile)
generates a config.ini
-File with the order:
[DEFAULT]
shape_weights = [1024, 1024, 1]
# [... some of the other options ...]
shuffle = True
augment = True
data_layer_type = hdf5
# [... some of the other options ...]
shape_img = [1024, 1024, 4]
# [... some of the other options ...]
shape_label = [1024, 1024, 1]
i.e. the entries are neither in alphabetic nor in any other recognizable order. But I want order, e.g. the shape options all in the same place and not distributed for the user to browse...
Here it is stated that the unordered behavior was fixed in Python 3.1 to use ordered dicts by default, but I am using Python 3.5.2 and get unordered entries. Is there a flag I need to set or a way to sort the dict so that it will result in (at least) alphabetically sorted entries?
Is there a way to define order of the entries when programmatically generating the config.ini
with the configparser? (Python 3.5)
回答1:
The issue here is not that configparser
isn't using OrderedDict
s internally, it's that you're making an unordered literal and assigning that.
Notice how this is not ordered:
>>> x = {
... 'shuffle': 'True',
... 'augment': 'True',
... # [... some other options ...]
... 'data_layer_type' : 'hdf5',
... 'shape_img' : '[1024, 1024, 4]',
... 'shape_label' : '[1024, 1024, 1]',
... 'shape_weights' : '[1024, 1024, 1]'
... }
>>> for k in x:
... print(k)
...
shuffle
augment
shape_img
shape_label
shape_weights
data_layer_type
(This changes as an implementation detail in python3.6 as part of a "small dicts" optimization (all dicts become ordered) -- likely to be standardized as part of python3.7 due to convenience)
The fix here is to make sure you're assigning OrderedDict
s all the way through:
config['DEFAULT'] = collections.OrderedDict((
('shuffle', 'True'),
('augment', 'True'),
# [... some other options ...]
('data_layer_type', 'hdf5'),
('shape_img', '[1024, 1024, 4]'),
('shape_label', '[1024, 1024, 1]'),
('shape_weights', '[1024, 1024, 1]'),
))
回答2:
The configparser seems to use OrderedDicts by default (since Python 2.7 / 3.1), which makes ConfigParser(dict_type=OrderedDict)
obsolete. However this doesn't order entries by default, one still has to do that manually (at least in my case).
I found code to do that here and added ordering defaults as well:
import configparser
from collections import OrderedDict
# [...] define your config sections and set values here
#Order the content of DEFAULT section alphabetically
config._defaults = OrderedDict(sorted(config._defaults.items(), key=lambda t: t[0]))
#Order the content of each section alphabetically
for section in config._sections:
config._sections[section] = OrderedDict(sorted(config._sections[section].items(), key=lambda t: t[0]))
# Order all sections alphabetically
config._sections = OrderedDict(sorted(config._sections.items(), key=lambda t: t[0] ))
来源:https://stackoverflow.com/questions/49722215/define-order-of-config-ini-entries-when-writing-to-file-with-configparser