6

RawConfigParser.write() メソッドに設定ファイルをアルファベット順にエクスポートさせる解決策はありますか?

元の/読み込まれた構成ファイルがソートされていても、モジュールはセクションとオプションをセクションに任意に混在させ、ソートされていない巨大な構成ファイルを手動で編集するのは本当に面倒です。

PD: Python 2.6 を使用しています

4

5 に答える 5

3

3 つのソリューション:

  1. 好みの並べ替え順序でキーを返す dict 型 (コンストラクターへの 2 番目の引数) を渡します。
  2. クラスとオーバーロードを拡張しwrite()ます (元のソースからこのメソッドをコピーして変更するだけです)。
  3. ファイル ConfigParser.py をコピーし、メソッドに並べ替えを追加しますwrite()

順序付けされた辞書については、この記事を参照するか、元の追加順序を保持するこの実装を使用してください。

于 2009-12-31T10:08:40.653 に答える
2

これは、構成ファイルをアルファベット順に書き込むための私のソリューションです。

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")    
于 2010-10-01T10:08:31.733 に答える
1

最初の方法は、最も簡単で安全な方法のように見えました。

しかし、ConfigParser のソース コードを見ると、空の組み込み dict が作成され、「2 番目のパラメーター」からすべての値が 1 つずつコピーされます。つまり、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

1 つだけ欠陥が残っています...つまり ConfigParser.items() にあります。updateodict はサポートされておらずcomparison、通常の dict を使用しています。

回避策 (この関数もオーバーロードします):

    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 のリーダー機能は非常にばかげています。とにかく、変更する必要があるのは 1 行だけです - そして、外部ファイルでオーバーロードするためにいくつかの他の行を変更する必要がありました:

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 から完全にコピーして貼り付けました

それで、全体的に何をすべきか?

  1. 以前に提案されたリンクの 1 つから odict.py をダウンロードします。
  2. インポートします。
  3. これらのコードをお気に入りの utils.py にコピー アンド ペーストします (OrderedRawConfigParserクラスが作成されます)。
  4. cfg = utils.OrderedRawConfigParser(odict.OrderedDict())
  5. いつものようにcfgを使用してください。それは順序付けられたままになります。
  6. 座って、ハバナを吸って、リラックスしてください。

PS3: ここで解決した問題は Python 2.5 のみです。2.6 には、すでにその解決策があります。彼ら__init__は、カスタム dict_type である関数に 2 番目のカスタム パラメーターを作成しました。

したがって、この回避策は 2.5 でのみ必要です

于 2010-03-10T16:04:27.273 に答える
0

サブツリーのマージを行う.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
于 2013-05-12T00:51:30.630 に答える