簡體   English   中英

將 python 對象轉儲為 yaml 文件

[英]dump an python object as yaml file

我在將下面顯示的 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.safe_dump

  yaml.safe_dump(brandObject, file)

但我收到了這個錯誤:

yaml.representer.RepresenterError: cannot represent an object: Canon: /cameras/canon/

這個對象有問題嗎?

這是一篇舊帖子,但要補充Jayanth Koushik 的回答

不確定沒有實現__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 文檔中找到:“ 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 文檔

如果你仍然想要safe_dump怎么safe_dump 沒有dump和麻煩為每個對象編寫一個代表,也沒有另一個依賴?

好吧,您可以編寫一個方法來捕獲所有內容,例如JSON SafeRepresenter的“默認”參數,並覆蓋在 YAML SafeRepresenter引發異常的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特定主題,請參閱:通過PyYAML 序列化namedtuples

您需要為該類實現 __repr__ 。 您可以將 __str__ 用作 __repr__。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM