21

PyYaml を使用して、独自の Python オブジェクトから Yaml ドキュメントを作成しています。たとえば、私のオブジェクト:

class MyObj(object):
    name = "boby"
    age = 34

になります:

boby:
   age: 34

ここまでは順調ですね。

しかし、生成された yaml にプログラムでコメントを追加する方法が見つからないため、次のようになります。

boby:       # this is the name
   age: 34  # in years

PyYaml のドキュメントとコードを見て、そうする方法が見つかりませんでした。

助言がありますか?

4

2 に答える 2

5

デフォルトでは、PyYAML を使用してダンプ ( print(yaml.dump(MyObj()))) すると、次のようになります。

!!python/object:__main__.MyObj {}

PyYAML は、目的の出力のコメントに対して 1 つのことしか実行できません: それらを破棄します。目的の出力を読み戻すと、dict を含む dict になります (タグ情報が{'boby': {'age': 34}}ないため、インスタンスは取得されません)。MyObj()

私が開発した PyYAML の拡張バージョン ( ruamel.yaml ) は、YAML をコメント付きで読み取り、コメントを保持し、ダンプ時にコメントを書き込むことができます。目的の出力を読み取ると、結果のデータは dict を含む dict のように見えます (そして動作します) が、実際にはコメントを処理できるより複雑なデータ構造があります。ただし、ruamel.yaml が のインスタンスをダンプするように要求したときにその構造を作成できますMyObj。そのときにコメントを追加すると、目的の出力が得られます。

from __future__ import print_function

import sys
import ruamel.yaml
from ruamel.yaml.comments import CommentedMap


class MyObj():
    name = "boby"
    age = 34

    def convert_to_yaml_struct(self):
        x = CommentedMap()
        a = CommentedMap()
        x[data.name] = a
        x.yaml_add_eol_comment('this is the name', 'boby', 11)
        a['age'] = data.age
        a.yaml_add_eol_comment('in years', 'age', 11)
        return x

    @staticmethod
    def yaml_representer(dumper, data, flow_style=False):
        assert isinstance(dumper, ruamel.yaml.RoundTripDumper)
        return dumper.represent_dict(data.convert_to_yaml_struct())


ruamel.yaml.RoundTripDumper.add_representer(MyObj, MyObj.yaml_representer)

ruamel.yaml.round_trip_dump(MyObj(), sys.stdout)

どちらが印刷されますか:

boby:      # this is the name
  age: 34  # in years

CommentedMapインスタンスを表現するまで、インスタンスの作成を待つ必要はありませんMyObj。たとえば、適切な から/に対して値を取得/設定するプロパティにnameとを作成します。そうすれば、インスタンスを表すために静的メソッドが呼び出される前に、コメントをより簡単に追加できます。ageCommentedMapyaml_representerMyObj

于 2015-04-15T12:14:09.797 に答える