4

Ruamel Python ライブラリを使用して、人間が編集した YAML ファイルをプログラムで編集しています。ソース ファイルには、アルファベット順に並べ替えられたキーがあります。

これが基本的な Python の質問なのか、Ruamel の質問なのかはわかりませんが、Ruamel の OrderedDict 構造をソートしようとしたすべての方法が失敗しています。

たとえば、このレシピに基づく次のコードが機能しない理由など、私は非常に混乱しています。

import ruamel.yaml
import collections

def read_file(f):
    with open(f, 'r') as _f:
        return ruamel.yaml.round_trip_load(
            _f.read(),
            preserve_quotes=True
        )

def write_file(f, data):
    with open(f, 'w') as _f:
        _f.write(ruamel.yaml.dump(
            data,
            Dumper=ruamel.yaml.RoundTripDumper,
            explicit_start=True,
            width=1024
        ))

data = read_file('in.yaml')
data = collections.OrderedDict(sorted(data.items(), key=lambda t: t[0]))
write_file('out.yaml', data)

しかし、この入力ファイルが与えられた場合:

---
bananas: 1
apples: 2

次の出力ファイルが生成されます。

--- !!omap
- apples: 2
- bananas: 1

つまり、ファイルが YAML 順序付きマップに変換されました。

これを行う簡単な方法はありますか?また、どういうわけかデータ構造に単純に挿入できますか?

4

1 に答える 1

5

ruamel.yaml¹ でマッピングを round_trip すると、マッピングはとして表されずcollections.OrderedDict()、 として表されますruamel.yaml.comments.CommentedMap()。後者は、collections.OrderedDict()使用している Python のバージョンに応じて のサブクラスになる場合があります (たとえば、Python 2 では、より高速な C 実装を使用しますruamel.ordereddict) 。

round_trip_dump モードでは、representerは「通常の」順序付けされた辞書 ( fromcollectionsまたは) を特別なものとして自動的に解釈しません。ruamel.ordereddictしかし、あなたがドロップした場合collections:

import ruamel.yaml

def read_file(f):
    with open(f, 'r') as _f:
        return ruamel.yaml.round_trip_load(
            _f.read(),
            preserve_quotes=True
        )

def write_file(f, data):
    with open(f, 'w') as _f:
        ruamel.yaml.dump(
            data,
            stream=_f,
            Dumper=ruamel.yaml.RoundTripDumper,
            explicit_start=True,
            width=1024
        )

data = read_file('in.yaml')
data = ruamel.yaml.comments.CommentedMap(sorted(data.items(), key=lambda t: t[0]))
write_file('out.yaml', data)

あなたは次のout.yamlようになります:

---
apples: 2
bananas: 1

write_file私はあなたのルーチンの非効率性も取り除いたことに注意してください。ストリームを指定しない場合、すべてのデータはStringIO最初に (メモリ内の) インスタンスにストリーミングされてから返されます (これは でストリーム_f.write()に書き込まれます。ストリームに直接書き込む方がはるかに効率的です。

最後の質問については、はい、次を使用して挿入できます。

data.insert(1, 'apricot', 3)

¹免責事項: 私はruamel.yamlruamel.ordereddictの両方の作成者です。

于 2016-09-03T15:02:57.220 に答える