I am having problems dumping the Python object shown below to a yaml file. I was wondering whether there is any specific object type/format.
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
This object contains a list of objects, and I tried to use yaml.safe_dump
yaml.safe_dump(brandObject, file)
But I got this error:
yaml.representer.RepresenterError: cannot represent an object: Canon: /cameras/canon/
Is there a problem with this object?
This is an old post but to complement Jayanth Koushik's answer:
Not sure that having __repr__
not implemented is the culprit here. I tried implementing it and it still raises an error, so the solution is probably not correct:
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))
still raises yaml.representer.RepresenterError: cannot represent an object: foo: http://foo.com
Actually the answer can be found in PyYaml documentation: "safe_dump
produces only standard YAML tags and cannot represent an arbitrary Python object.". Therefore you simply need to use dump
instead of safe_dump
:
>>> print(yaml.dump(brand_object))
!!python/object:__main__.CameraBrand
models: []
name: foo
rank: ''
url: http://foo.com
However, once you do that, you will see that loading your object back
yaml.load
, safe_load
. For this you would have to dig a little bit into YAMLObject
and other PyYaml classes, and that is a bit tricky.Alternatively, you can use the yamlable library, which automates a few of these PyYaml tricks for you. I wrote it to solve similar cases in our production code, in order to make it easier to control the object-to-yaml binding process. In your case, the following would do the trick:
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))
yields
!yamlable/myyaml.CameraBrand {name: foo, url: 'http://foo.com'}
and
print(yaml.safe_load("""!yamlable/myyaml.CameraBrand
name: foo
url: http://bar.com
"""))
loads the object correctly back and displays its string representation:
foo: http://bar.com
Note that you can also uncomment the from_yaml_dict
method if you wish to perform some custom action when loading the object. See yamlable documentation for details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With