如何为 PyYAML 编写表示器?

Posted

技术标签:

【中文标题】如何为 PyYAML 编写表示器?【英文标题】:How do I write a representer for PyYAML? 【发布时间】:2011-11-03 06:25:38 【问题描述】:

我想要一个自定义函数来序列化任意 python 对象,例如 json.dump 函数如何具有一个名为“default”的可选参数,如果对象不是 json 可序列化对象,则该函数应该是 json 转储程序将调用的函数.

我只是想从 json 包中做同样的事情。

json.dump(tests_dump, file('somefile', 'w+'), default = lambda x: x.__dict__)

看起来我需要从 PyYAML 文档中编写 yaml.add_representer,但确实不清楚如何执行此操作。

【问题讨论】:

【参考方案1】:

这是 add_representer 的示例。不确定这是否正是您想要的。不过……

import yaml

#Arbitrary Class
class MyClass:
  def __init__(self, someNumber, someString):
    self.var1 = someNumber
    self.var2 = someString

#define the representer, responsible for serialization
def MyClass_representer(dumper, data):
    serializedData = str(data.var1) + "|" + data.var2
    return dumper.represent_scalar('!MyClass', serializedData )

#'register' it     
yaml.add_representer(MyClass, MyClass_representer)

obj = MyClass(100,'test')

print ( 'original Object\nvar1:0, var2:1\n'.format(obj.var1, obj.var2) )

#serialize
yamlData = yaml.dump(obj)

print('serialized as:\n0'.format(yamlData) )

#Now to deserialize you need a constructor
def MyClass_constructor(loader,node):
    value = loader.construct_scalar(node)
    someNumber,sep,someString = value.partition("|")
    return MyClass(someNumber,someString)

#'register' it    
yaml.add_constructor('!MyClass', MyClass_constructor)

#deserialize
obj2 = yaml.load(yamlData)

print ( 'after deserialization\nvar1:0, var2:1\n'.format(obj2.var1, obj2.var2) )

当然有代码重复,代码没有优化。您可以将这两个函数作为您的类的一部分,还可以实现 __repr__ 以获得可打印的表示形式,您可以使用该表示形式在 MyClass_representer 中填充 serializedData

【讨论】:

那么我如何“注销”添加的表示器和构造器?我在一个有其他工具依赖于不同行为的环境中工作,我发现如果我像这样添加表示器和构造函数,它会改变 yaml 模块的行为,即使调用 yaml 的代码在另一个文件中模块。 如何使这个工作适用于类的层次结构(比如 A(roor)、B(root)、C(root))? @VeltzerDoron 如果你使用add_multi_representer,它会被子类调用。

以上是关于如何为 PyYAML 编写表示器?的主要内容,如果未能解决你的问题,请参考以下文章

Python中Pyyaml模块的使用

如何加载 pyYAML 文件并使用属性而不是使用字典表示法访问它?

pyyaml 的漂亮输出

使用 PyYAML 库解析 AWS CloudFormation 模板

pyyaml 中的默认构造函数参数

Python + PyYAML 读取yaml配置文件数据