タイプリファレンスをメンバーとするクラスをYAML直列化するのに問題があります。私はruamel.yamlの安全なローダーを使用しています。YAML - 型である属性をシリアライズ
私はREPLプロンプトから以下のすべてを実行しました(複数のエラーを取得するため)。
初期化:故障の原因となる
import sys
from ruamel.yaml import YAML, yaml_object
Y = YAML(typ="safe",pure=True)
# ==============
@yaml_object(Y)
class A(object):
"""Object I want to serialize"""
yaml_tag = "!Aclass"
def __init__(self, type):
self.type = type
def f(self):
return self.type()
pass
class T1(object):
"""This will be referenced."""
pass
@yaml_object(Y)
class T2(object):
"""Another referenced object"""
pass
class T3(object):
"""Yet another try"""
pass
Y.register_class(T3.__class__)
コード:
Y.dump(A(T1), sys.stdout)
Y.dump(A(T2), sys.stdout)
Y.dump(A(T3), sys.stdout)
Y.dump(A(int), sys.stdout)
この出力(トレースバックの最後の行):
ruamel.yaml.representer.RepresenterError: cannot represent an object: <attribute '__dict__' of 'T1' objects>
ruamel.yaml.representer.RepresenterError: cannot represent an object: <attribute '__dict__' of 'T2' objects>
ruamel.yaml.representer.RepresenterError: cannot represent an object: <attribute '__dict__' of 'T3' objects>
ruamel.yaml.representer.RepresenterError: cannot represent an object: <slot wrapper '__abs__' of 'int' objects>
私をすることができます任意の溶液(安全に)型を一意に保存する(私は型のオブジェクトを生成し、入ってくるオブジェクトが特定のタイプのものであることが理解されよう)。必要な型を生成する関数またはクラスは、直列化できないという同じ問題を抱えています。
P.S.私はバグを発見したこともあります。パーサーは何らかの理由で、同じ有効な議論が連載されようとしているかどうかに応じて動作が異なります。
Y.dump(A(str), sys.stdout)
Y.dump(A(str), sys.stdout)
Y.dump(A(str), sys.stdout)
Y.dump(A(str), sys.stdout)
出力:
>>> Y.dump(A(str), sys.stdout)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\main.py", line 352, in dump
return self.dump_all([data], stream, _kw, transform=transform)
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\main.py", line 383, in dump_all
self.representer.represent(data)
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 73, in represent
node = self.represent_data(data)
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 101, in represent_data
node = self.yaml_representers[data_types[0]](self, data)
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\main.py", line 552, in t_y
tag, data, cls, flow_style=representer.default_flow_style)
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 371, in represent_yaml_object
return self.represent_mapping(tag, state, flow_style=flow_style)
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 206, in represent_mapping
node_value = self.represent_data(item_value)
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 101, in represent_data
node = self.yaml_representers[data_types[0]](self, data)
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\main.py", line 492, in t_y
tag, data, cls, flow_style=representer.default_flow_style)
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 371, in represent_yaml_object
return self.represent_mapping(tag, state, flow_style=flow_style)
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 206, in represent_mapping
node_value = self.represent_data(item_value)
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 111, in represent_data
node = self.yaml_representers[None](self, data)
File "C:\Program Files\Anaconda3\lib\site-packages\ruamel\yaml\representer.py", line 375, in represent_undefined
raise RepresenterError("cannot represent an object: %s" % data)
ruamel.yaml.representer.RepresenterError: cannot represent an object: <slot wrapper '__add__' of 'str' objects>
>>> Y.dump(A(str), sys.stdout)
!Aclass
type: !type {}
>>> Y.dump(A(str), sys.stdout)
Traceback (most recent call last):
# same traceback here
ruamel.yaml.representer.RepresenterError: cannot represent an object: <slot wrapper '__add__' of 'str' objects>
>>> Y.dump(A(str), sys.stdout)
!Aclass
type: !type {}
>>>
いいえ、それはうまくいくようです。私の中のT2。 _However_、私は与えられたクラスのオブジェクトを構築するので、Yはオブジェクトをロードするのが安全かどうかを(少なくともあなたの実装からは)知ることができないので、コードに悪質な型をロードしている可能性があります。この場合、クラスが登録されていなくても、T1は「ロードされました」。 1つの可能な修正は、見つかったクラスがYによって登録されているかどうか(つまり、constructor.yaml_constructors?)A.from_yaml()をチェックすることです。第2の部分に関しては、それは理にかなっている。 –
あなたは安全については正しいと思っていますが、答えに取り組んでいる間にそれについて考えましたが、それを含めるのを忘れました。私はすべての関連する型をモジュール(またはサブディレクトリ内の複数のモジュール)に入れ、そこからインポートします。次に、 'A'の' from_yaml() 'の' node.value'の文字列をチェックすることができます。テストする(一意の)属性を設定する独自の '@ yaml_type'を作成することもできます(ダンプやロード時に)。 ruamel.yamlのオブジェクトの登録を再利用する必要はありません(本質的には別のものです)。 – Anthon
私は私の答えで小さなモックアップを作った、それを安全にするためにそれを(または自分の答え)を自由に変更してください。編集:私は投稿している間あなたのコメントを逃した、あなたはそれが何を意味するかはっきりしない? @yaml_typeデコレータを使ってオブジェクトの隠し属性を設定することを意味しますか?誰かが自分のクラスに同じことをして私たちを偽装するのを妨げるのは何ですか? –