是否有解決方案強制RawConfigParser.write()方法導出按字母排序的配置文件?導出在Python中按字母順序排序ConfigParser
即使對原始/加載的配置文件進行排序,模塊也會將段落和選項任意混合到段中,而且真的很煩人手動編輯一個巨大的未排序配置文件。
PD:我使用python 2.6
是否有解決方案強制RawConfigParser.write()方法導出按字母排序的配置文件?導出在Python中按字母順序排序ConfigParser
即使對原始/加載的配置文件進行排序,模塊也會將段落和選項任意混合到段中,而且真的很煩人手動編輯一個巨大的未排序配置文件。
PD:我使用python 2.6
三種解決方案:
write()
(只需從原始源複製此方法並對其進行修改)。write()
。請參閱this article對於有序字典或可能使用this implementation保留原始添加順序。
第一種方法看起來是最簡單,最安全的方法。
但是,在查看ConfigParser的源代碼之後,它會創建一個空的內置字典,然後從「第二個參數」一個接一個地複製所有值。這意味着它不會使用OrderedDict類型。一個簡單的解決方法可以是重載CreateParser類。
class OrderedRawConfigParser(ConfigParser.RawConfigParser):
def __init__(self, defaults=None):
self._defaults = type(defaults)() ## will be correct with all type of dict.
self._sections = type(defaults)()
if defaults:
for key, value in defaults.items():
self._defaults[self.optionxform(key)] = value
它只留下一個缺陷......即在ConfigParser.items()中。 odict不支持update
和comparison
正常的字典。
解決方法(重載這個功能太):
def items(self, section):
try:
d2 = self._sections[section]
except KeyError:
if section != DEFAULTSECT:
raise NoSectionError(section)
d2 = type(self._section)() ## Originally: d2 = {}
d = self._defaults.copy()
d.update(d2) ## No more unsupported dict-odict incompatibility here.
if "__name__" in d:
del d["__name__"]
return d.items()
其他解決項目問題是修改odict.OrderedDict.update
功能 - 這可能是比這多了一個簡單的,但我把它留給你。 PS:我實現了這個解決方案,但它不起作用。如果我弄清楚,ConfigParser仍在混合條目的順序,我會報告它。
PS2:已解決。 ConfigParser的閱讀器功能相當笨蛋。總之,只有一行,就必須改變 - 和其他一些人在一個外部文件超載:
def _read(self, fp, fpname):
cursect = None
optname = None
lineno = 0
e = None
while True:
line = fp.readline()
if not line:
break
lineno = lineno + 1
if line.strip() == '' or line[0] in '#;':
continue
if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
continue
if line[0].isspace() and cursect is not None and optname:
value = line.strip()
if value:
cursect[optname] = "%s\n%s" % (cursect[optname], value)
else:
mo = self.SECTCRE.match(line)
if mo:
sectname = mo.group('header')
if sectname in self._sections:
cursect = self._sections[sectname]
## Add ConfigParser for external overloading
elif sectname == ConfigParser.DEFAULTSECT:
cursect = self._defaults
else:
## The tiny single modification needed
cursect = type(self._sections)() ## cursect = {'__name__':sectname}
cursect['__name__'] = sectname
self._sections[sectname] = cursect
optname = None
elif cursect is None:
raise ConfigParser.MissingSectionHeaderError(fpname, lineno, line)
## Add ConfigParser for external overloading.
else:
mo = self.OPTCRE.match(line)
if mo:
optname, vi, optval = mo.group('option', 'vi', 'value')
if vi in ('=', ':') and ';' in optval:
pos = optval.find(';')
if pos != -1 and optval[pos-1].isspace():
optval = optval[:pos]
optval = optval.strip()
if optval == '""':
optval = ''
optname = self.optionxform(optname.rstrip())
cursect[optname] = optval
else:
if not e:
e = ConfigParser.ParsingError(fpname)
## Add ConfigParser for external overloading
e.append(lineno, repr(line))
if e:
raise e
相信我,我沒有寫這個東西。我複製粘貼它完全從ConfigParser.py
那麼整體該怎麼做?從一個鏈接
OrderedRawConfigParser
類)cfg = utils.OrderedRawConfigParser(odict.OrderedDict())
PS3:我在這裏解決的問題只在Python 2.5中。在2.6中已經有了一個解決方案。他們在__init__
函數中創建了第二個自定義參數,這是一個自定義的dict_type。
所以才需要這個解決方法2.5
這是我在字母排序寫配置文件的解決方案:
class OrderedRawConfigParser(ConfigParser.RawConfigParser):
"""
Overload standart Class ConfigParser.RawConfigParser
"""
def __init__(self, defaults = None, dict_type = dict):
ConfigParser.RawConfigParser.__init__(self, defaults = None, dict_type = dict)
def write(self, fp):
"""Write an .ini-format representation of the configuration state."""
if self._defaults:
fp.write("[%s]\n" % DEFAULTSECT)
for key in sorted(self._defaults):
fp.write("%s = %s\n" % (key, str(self._defaults[ key ]).replace('\n', '\n\t')))
fp.write("\n")
for section in self._sections:
fp.write("[%s]\n" % section)
for key in sorted(self._sections[section]):
if key != "__name__":
fp.write("%s = %s\n" %
(key, str(self._sections[section][ key ]).replace('\n', '\n\t')))
fp.write("\n")
有幫助,但未定義DEFAULTSECT。並將「排序(self._sections)」部分:「 –
我一直在尋找這個用於合併.gitmodules做一個子樹合併一個超級模塊 - 開始時感到非常困惑,並且對子模塊有不同的命令令人困惑,哈哈。
使用GitPython幫助了很多:
from collections import OrderedDict
import git
filePath = '/tmp/git.config'
# Could use SubmoduleConfigParser to get fancier
c = git.GitConfigParser(filePath, False)
c.sections()
# http://stackoverflow.com/questions/8031418/how-to-sort-ordereddict-in-ordereddict-python
c._sections = OrderedDict(sorted(c._sections.iteritems(), key=lambda x: x[0]))
c.write()
del c
我能夠從外部排序在ConfigParser的部分,像這樣來解決這個問題:
config = ConfigParser.ConfigParser({}, collections.OrderedDict)
config.read('testfile.ini')
# Order the content of each section alphabetically
for section in config._sections:
config._sections[section] = collections.OrderedDict(sorted(config._sections[section].items(), key=lambda t: t[0]))
# Order all sections alphabetically
config._sections = collections.OrderedDict(sorted(config._sections.items(), key=lambda t: t[0]))
# Write ini file to standard output
config.write(sys.stdout)
雖然這個工程,這有缺點,從'testfile.ini'的順序不會保留。 –
這是正確的。我的解決方案按字母順序排列各個部分,並且在每個部分中,所有的鍵都按字母順序排序如果您只想保留原來的順序,那麼只需要解決方案的前兩行。 –
請參閱我的答案是第四個,工作,解決方案。 –