2

これは私がやろうとしていることです (コードは Python 3 にあります):

import ruamel.yaml as yaml
from print import pprint

yaml_document_with_aliases = """
title: test
choices: &C
  a: one
  b: two
  c: three
---
title: test 2
choices: *C
"""

items = list(yaml.load_all(yaml_document_with_aliases))

結果は次のとおりです。

ComposerError: found undefined alias 'C'

非ドキュメントベースの YAML ファイルを使用している場合、これは期待どおりに機能します。

import ruamel.yaml as yaml
from print import pprint

yaml_nodes_with_aliases = """
-
  title: test
  choices: &C
    a: one
    b: two
    c: three
-
  title: test 2
  choices: *C
"""

items = yaml.load(yaml_nodes_with_aliases)

pprint(items)

結果:

[{'choices': {'a': 'one', 'b': 'two', 'c': 'three'}, 'title': 'test'},
 {'choices': {'a': 'one', 'b': 'two', 'c': 'three'}, 'title': 'test 2'}]

(とにかくやりたかったこと)


現時点では不可能なので、次の脆弱な回避策を使用しています。

def yaml_load_all_with_aliases(yaml_text):
    if not yaml_text.startswith('---'):
        yaml_text = '---\n' + yaml_text
    for pat, repl in [('^', '  '), ('^\s*---\s*$', '-'), ('^\s+\.{3}$\n', '')]:
        yaml_text = re.sub(pat, repl, yaml_text, flags=re.MULTILINE)
    yaml_text = yaml_text.strip()
    return yaml.safe_load(yaml_text)
4

1 に答える 1

1

ここでの問題は次のとおりです。

title: test
choices: &C
  a: one
  b: two
  c: three
---
title: test 2
choices: *C

はドキュメントではありませんこれらは 1 つのファイルに 2 つの YAML ドキュメントです。アンカー定義&Cは、ある YAML ドキュメントから別の YAML ドキュメントに引き継がれません。ドキュメント セパレーターまでしか使用できません---

すべてのアンカーを単一の YAML ストリーム内の次のドキュメントに「引き継ぐ」場合はcompose_document、クラスに新しいメソッドを移植できますComposer(つまり、モンキー パッチを適用します)。

import sys
import ruamel.yaml

yaml_str = """\
title: test
choices: &C
  a: one
  b: two
  c: three
---
title: test 2
choices: *C
"""


def my_compose_document(self):
    self.get_event()
    node = self.compose_node(None, None)
    self.get_event()
    # this prevents cleaning of anchors between documents in **one stream**
    # self.anchors = {}
    return node

ruamel.yaml.composer.Composer.compose_document = my_compose_document

datas = []
for data in ruamel.yaml.safe_load_all(yaml_str):
    datas.append(data)

datas[0]['choices']['a'] = 1
for data in datas:
    ruamel.yaml.round_trip_dump(data, sys.stdout, explicit_start=True)

与える:

---
title: test
choices:
  a: 1
  b: two
  c: three
---
title: test 2
choices:
  a: one
  b: two
  c: three

これにより、キー、、およびを持つ dictのコピーが取得されることに注意してください。abc

(キーの順序付けとコメントの保存が重要な場合は、round_trip_load_all代わりに使用しますsafe_load_all)

于 2016-11-20T08:35:51.493 に答える