5

PyYAML の dump() 関数によって生成された YAML でアンカーを生成できるようにしたいと考えています。これを行う方法はありますか?アンカーの名前が YAML ノードと同じであることが理想的です。

例:

import yaml
yaml.dump({'a': [1,2,3]})
'a: [1, 2, 3]\n'

私ができるようにしたいのは、次のような YAML を生成することです。

import yaml
yaml.dump({'a': [1,2,3]})
'a: &a [1, 2, 3]\n'

これを行うためのカスタム エミッタまたはダンパーを作成できますか? 別の方法はありますか?

4

5 に答える 5

3

デフォルトでは、アンカーは、以前に見たオブジェクトへの参照を検出した場合にのみ発行されます。

>>> import yaml
>>>
>>> foo = {'a': [1,2,3]}
>>> doc = (foo,foo)
>>>
>>> print yaml.safe_dump(doc, default_flow_style=False)
- &id001
  a:
  - 1
  - 2
  - 3
- *id001

名前の付け方をオーバーライドしたい場合は、Dumper クラス、特にgenerate_anchor()関数をカスタマイズする必要があります。ANCHOR_TEMPLATEも役立つ場合があります。

あなたの例では、ノード名は単純ですが、YAML 値の多くの可能性を考慮する必要があります。つまり、単一の値ではなくシーケンスである可能性があります。

>>> import yaml
>>>
>>> foo = {('a', 'b', 'c'): [1,2,3]}
>>> doc = (foo,foo)
>>>
>>> print yaml.dump(doc, default_flow_style=False)
!!python/tuple
- &id001
  ? !!python/tuple
  - a
  - b
  - c
  : - 1
    - 2
    - 3
- *id001
于 2014-04-02T21:52:28.333 に答える
2

最上位ノードのアンカー値を強制するカスタム アンカー クラスを作成しました。単純にアンカー文字列をオーバーライドする (generate_anchor を使用) のではなく、ノードが後で参照されない場合でも、実際には Anchor を強制的に発行します。

class CustomAnchor(yaml.Dumper):
    def __init__(self, *args, **kwargs):
        super(CustomAnchor, self).__init__(*args, **kwargs)
        self.depth = 0
        self.basekey = None
        self.newanchors = {}

    def anchor_node(self, node):
        self.depth += 1
        if self.depth == 2:
            assert isinstance(node, yaml.ScalarNode), "yaml node not a string: %s" % node
            self.basekey = str(node.value)
            node.value = self.basekey + "_ALIAS"
        if self.depth == 3:
            assert self.basekey, "could not find base key for value: %s" % node
            self.newanchors[node] = self.basekey
        super(CustomAnchor, self).anchor_node(node)
        if self.newanchors:
            self.anchors.update(self.newanchors)
            self.newanchors.clear()

ノード名をオーバーライドして「_ALIAS」という接尾辞を付けますが、その行を削除してノード名とアンカー名を同じままにするか、別のものに変更することができます。

たとえば、 {'FOO': 'BAR'} をダンプすると、次のようになります。

FOO_ALIAS: &FOO BAR

また、一度に 1 つのトップ レベルのキーと値のペアを処理するためにのみ記述し、トップ レベルのキーのアンカーのみを強制します。すべてのキーが最上位の YAML ノードである YAML ファイルに dict を変換する場合は、dict を反復処理し、各キーと値のペアを {key:value} としてダンプするか、このクラスを書き直して、複数のキーを持つ dict 。

于 2016-03-29T22:06:45.713 に答える