3

2 つのドキュメントを含む 1 つの yaml ファイルに書き込みたい 2 つの Python 辞書があります。

definitions = {"one" : 1, "two" : 2, "three" : 3}
actions = {"run" : "yes", "print" : "no", "report" : "maybe"}

yaml ファイルは次のようになります。

--- !define
one: 1
two: 2
three: 3

-- !action
run: yes
print: no
report: maybe
...

PyYaml を使用しても、それを行う明確な方法が見つかりませんでした。簡単な方法があると確信していますが、PyYaml のドキュメントを掘り下げると、混乱するだけでした。ダンパーやエミッターなどが必要ですか? そして、これらの各タイプが生成する出力のタイプは何ですか? Yaml テキスト? yaml ノード? YAMLオブジェクト? とにかく、説明に感謝します。


以下のunutbuの回答に続いて、これが私が思いつくことができる最も簡潔なバージョンです:

DeriveYAMLObjectWithTag は、必要なタグを持つ YAMLObject から派生した新しいクラスを作成する関数です。

def DeriveYAMLObjectWithTag(tag):
    def init_DeriveYAMLObjectWithTag(self, **kwargs):
        """ __init__ for the new class """
        self.__dict__.update(kwargs)

    new_class = type('YAMLObjectWithTag_'+tag,
                    (yaml.YAMLObject,),
                    {'yaml_tag' : '!{n}'.format(n = tag),
                    '__init__' :  init_DeriveYAMLObjectWithTag})
    return new_class

次に、DeriveYAMLObjectWithTag を使用して必要な Yaml を取得する方法を示します。

definitions = {"one" : 1, "two" : 2, "three" : 3, "four" : 4}
actions = {"run" : "yes", "print" : "no", "report" : "maybe"}
namespace = [DeriveYAMLObjectWithTag('define')(**definitions),
             DeriveYAMLObjectWithTag('action')(**actions)]

text = yaml.dump_all(namespace,
                     default_flow_style = False,
                     explicit_start = True)

答えてくれたすべての人に感謝します。PyYaml には機能が不足しているようですが、これはそれを克服する最もエレガントな方法です。

4

2 に答える 2

7

まあ、私はまだ自動コメントを調べています(すぐにドキュメントを見つけることができませんでした)が、これでうまくいくはずです:

import yaml

definitions = {"one" : 1, "two" : 2, "three" : 3}
actions = {"run" : "yes", "print" : "no", "report" : "maybe"}

output = yaml.dump(actions, default_flow_style=False, explicit_start=True)
output += yaml.dump(definitions, default_flow_style=False, explicit_start=True)

print output

注意点として、辞書は順序付けされていないため、結果の YAML の順序は保証されません。家で注文したい場合は、OrderedDictを見てください。

于 2013-01-01T17:07:08.400 に答える
1

どうですか:

class Bunch(yaml.YAMLObject):
    yaml_tag = u'!Bunch'
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)
    def __repr__(self):
        return '{c}({a})'.format(
            c = self.__class__.__name__,
            a = ', '.join(
                ['='.join(map(str,item)) for item in self.__dict__.items()]))
tag_names = ['define', 'action']
namespace = {}
for name in tag_names:
    namespace[name] = type(name, (Bunch,), {'yaml_tag':u'!{n}'.format(n = name)})

definitions = {"one" : 1, "two" : 2, "three" : 3}
actions = {"run" : "yes", "print" : "no", "report" : "maybe"}
text = yaml.dump_all([namespace['define'](**definitions),
                      namespace['action'](**actions)],
                     default_flow_style = False,
                     explicit_start = True)
print(text)

利回り

--- !define
one: 1
three: 3
two: 2
--- !action
print: 'no'
report: maybe
run: 'yes'

YAML を Python オブジェクトにロードし直すには、次のようにします。

for item in  yaml.load_all(text):
    print(item)
    # define(one=1, three=3, two=2)
    # action(print=no, report=maybe, run=yes)

アプリケーション固有のタグを作成するために、YAMLObject のサブクラスが使用されました。

于 2013-01-01T17:09:53.613 に答える