ruamel.yaml python 类 包含属性的转储似乎会产生意外的 yaml 格式
ruamel.yaml dump of python classes containing properties seem to produce unexpected yaml formatting
我正在努力将 python class 数据转储到 YAML,以便稍后加载。我发现使用 ruamel.yaml(和 PyYAML)时,当我使用 属性 转储 class 来管理 class 属性时,YAML 输出更改为似乎无效的内容YAML 语法。我将下面的代码放在一起来演示行为
import sys
import ruamel.yaml
class MySampleClass(object):
def __init__(self, attribute1, attribute2):
self.attribute1 = attribute1
self.attribute2 = attribute2
@property
def attribute1(self):
return self.attribute1
@attribute1.setter
def attribute1(self, attribute1):
self.__attribute1 = attribute1
sample1 = MySampleClass("ABCD", "123")
yaml = ruamel.yaml.YAML()
yaml.register_class(MySampleClass)
yaml.dump(sample1, sys.stdout)
当 运行 这会产生下面的输出。如您所见,装饰的第一个 属性 具有意外的格式,而第二个是人们对 YAML 的期望。
!MySampleClass
_MySampleClass__attribute1: ABCD
attribute2: '1234'
有没有办法在不从头开始为每个 class 编写自定义构造函数和表示器的情况下克服这个问题?
ruamel.yaml
不将 properties/setters 处理为 "normal" 属性,这就是为什么你得到有趣的输出, 是 有效的 YAML .
首先你应该改变你的属性 1 属性,因为调用 print(sample1.attribute1)
会
让你进入无限递归。
然后你可以只创建一个具有适当 to_yaml
方法的基础 class
可用于转储所有 classes:
import sys
import ruamel.yaml
yaml = ruamel.yaml.YAML()
class ObjWithProperties(object):
@classmethod
def to_yaml(cls, representer, node):
tag = getattr(cls, 'yaml_tag', '!' + cls.__name__)
attribs = {}
for x in dir(node):
if x.startswith('_'):
continue
v = getattr(node, x)
if callable(v):
continue
attribs[x] = v
return representer.represent_mapping(tag, attribs)
@yaml.register_class
class MySampleClass(ObjWithProperties):
def __init__(self, attribute1, attribute2):
self.attribute1 = attribute1
self.attribute2 = attribute2
@property
def attribute1(self):
return self.__attribute1 # <<<< note the added double underscore to prevent recursion
@attribute1.setter
def attribute1(self, attribute1):
self.__attribute1 = attribute1
sample1 = MySampleClass("ABCD", "123")
yaml.dump(sample1, sys.stdout)
给出:
!MySampleClass
attribute1: ABCD
attribute2: '123'
我正在努力将 python class 数据转储到 YAML,以便稍后加载。我发现使用 ruamel.yaml(和 PyYAML)时,当我使用 属性 转储 class 来管理 class 属性时,YAML 输出更改为似乎无效的内容YAML 语法。我将下面的代码放在一起来演示行为
import sys
import ruamel.yaml
class MySampleClass(object):
def __init__(self, attribute1, attribute2):
self.attribute1 = attribute1
self.attribute2 = attribute2
@property
def attribute1(self):
return self.attribute1
@attribute1.setter
def attribute1(self, attribute1):
self.__attribute1 = attribute1
sample1 = MySampleClass("ABCD", "123")
yaml = ruamel.yaml.YAML()
yaml.register_class(MySampleClass)
yaml.dump(sample1, sys.stdout)
当 运行 这会产生下面的输出。如您所见,装饰的第一个 属性 具有意外的格式,而第二个是人们对 YAML 的期望。
!MySampleClass
_MySampleClass__attribute1: ABCD
attribute2: '1234'
有没有办法在不从头开始为每个 class 编写自定义构造函数和表示器的情况下克服这个问题?
ruamel.yaml
不将 properties/setters 处理为 "normal" 属性,这就是为什么你得到有趣的输出, 是 有效的 YAML .
首先你应该改变你的属性 1 属性,因为调用 print(sample1.attribute1)
会
让你进入无限递归。
然后你可以只创建一个具有适当 to_yaml
方法的基础 class
可用于转储所有 classes:
import sys
import ruamel.yaml
yaml = ruamel.yaml.YAML()
class ObjWithProperties(object):
@classmethod
def to_yaml(cls, representer, node):
tag = getattr(cls, 'yaml_tag', '!' + cls.__name__)
attribs = {}
for x in dir(node):
if x.startswith('_'):
continue
v = getattr(node, x)
if callable(v):
continue
attribs[x] = v
return representer.represent_mapping(tag, attribs)
@yaml.register_class
class MySampleClass(ObjWithProperties):
def __init__(self, attribute1, attribute2):
self.attribute1 = attribute1
self.attribute2 = attribute2
@property
def attribute1(self):
return self.__attribute1 # <<<< note the added double underscore to prevent recursion
@attribute1.setter
def attribute1(self, attribute1):
self.__attribute1 = attribute1
sample1 = MySampleClass("ABCD", "123")
yaml.dump(sample1, sys.stdout)
给出:
!MySampleClass
attribute1: ABCD
attribute2: '123'