我在将下面显示的Python对象转储到yaml文件时遇到问题。我想知道是否有任何特定的对象类型/格式。
class CameraBrand():
def __init__(self, name, url):
self.rank = ""
self.name = name
self.url = url
self.models = []
def __str__(self):
return self.name + ": " + self.url
此对象包含对象列表,我尝试使用yaml.save_dump
yaml.safe_dump(brandObject, file)
但我收到了这个错误:
yaml.representer.RepresenterError: cannot represent an object: Canon: /cameras/canon/
这个对象有问题吗?
答案 0 :(得分:5)
这是旧帖子,但补充了Jayanth Koushik's answer:
不确定造成__repr__
未实现的原因。我尝试实现它,但它仍然引发错误,因此解决方案可能不正确:
import yaml
class CameraBrand():
def __init__(self, name, url):
self.rank = ""
self.name = name
self.url = url
self.models = []
def __str__(self):
return repr(self)
def __repr__(self):
return self.name + ": " + self.url
brand_object = CameraBrand('foo', 'http://foo.com')
print(yaml.safe_dump(brand_object))
仍然提高yaml.representer.RepresenterError: cannot represent an object: foo: http://foo.com
实际上,答案可以在PyYaml documentation中找到:“ safe_dump
仅生成标准的YAML标签,不能表示任意的Python对象。”因此,您只需要使用dump
而不是safe_dump
:
>>> print(yaml.dump(brand_object))
!!python/object:__main__.CameraBrand
models: []
name: foo
rank: ''
url: http://foo.com
但是,一旦执行此操作,您将看到将对象加载回
yaml.load
safe_load
有点棘手。为此,您必须深入研究YAMLObject
和其他PyYaml类,这有点棘手。或者,您可以使用yamlable库,该库可以自动为您提供一些PyYaml技巧。我编写它的目的是为了解决生产代码中的类似情况,以便更轻松地控制对象到Yaml的绑定过程。在您的情况下,以下方法可以解决问题:
import yaml
from yamlable import YamlAble, yaml_info
@yaml_info(yaml_tag_ns='myyaml')
class CameraBrand(YamlAble):
def __init__(self, name, url):
self.rank = ""
self.name = name
self.url = url
self.models = []
def __str__(self):
return self.name + ": " + self.url
def to_yaml_dict(self):
return {'name': self.name, 'url': self.url}
# @classmethod
# def from_yaml_dict(cls, dct, yaml_tag):
# return CameraBrand(**dct)
brand_object = CameraBrand('foo', 'http://foo.com')
print(yaml.safe_dump(brand_object))
收益
!yamlable/myyaml.CameraBrand {name: foo, url: 'http://foo.com'}
和
print(yaml.safe_load("""!yamlable/myyaml.CameraBrand
name: foo
url: http://bar.com
"""))
正确地将对象加载回并显示其字符串表示形式:
foo: http://bar.com
请注意,如果希望在加载对象时执行一些自定义操作,也可以取消注释from_yaml_dict
方法。有关详细信息,请参见yamlable documentation。
答案 1 :(得分:1)
您需要为该类实现__repr__。您可以将__str__用作__repr __。
答案 2 :(得分:0)
如果您仍然想safe_dump
怎么办?
无需dump
并费心为每个对象编写一个表示符,也不必烦恼另一个依赖项吗?
好吧,您可以编写一个可以包罗万象的方法,例如JSON dumpers的“默认”参数,并覆盖在YAML SafeRepresenter
中引发异常的方法。
使用PyAML 3.12进行概念验证。
import yaml
yaml.SafeDumper.yaml_representers[None] = lambda self, data: \
yaml.representer.SafeRepresenter.represent_str(
self,
str(data),
)
示例:
>>> import collections
>>> yaml.safe_dump([collections.namedtuple('Foo', 'bar')(1)])
'[Foo(bar=1)]\n'
>>> yaml.safe_dump(CameraBrand('Canon', '/cameras/canon/'))
"'Canon: /cameras/canon/'\n"
注意:有关namedtuple
特定主题,请参见:Serializing namedtuples via PyYAML