我正在尝试为某些配置对象创建自定义YAML转储器/加载器。为简单起见,假设我们要将类CollectivePerson [id=1, addresses=[Address 1, Address 4], phones=[Phone 1, Phone 4]]
CollectivePerson [id=2, addresses=[Address 2, Address 6, Address 5], phones=[Phone 5, Phone 2, Phone 6]]
CollectivePerson [id=3, addresses=[Address 3], phones=[Phone 3]]
的对象转储到Hero
文件。
hero.yml
然后按class Hero:
yaml_tag = '!Hero'
def __init__(self, name, age):
self.name = name
self.age = age
ruamel.yaml
尝试转储并加载:
yaml.register_class(Hero)
完美无缺!
h = Hero('Saber', 15)
with open('config.yml', 'w') as fout:
yaml.dump(h, fout)
with open('config.yml') as fin:
yaml.load(fin)
和to_yaml
方法失败但是,当我需要更灵活的行为,因此需要自定义from_yaml
和from_yaml
方法时,就会出现问题。
to_yaml
的实施更改为:
Hero
翻斗车的工作方式与预期一致。但是加载无法加载YAML文件。一个 抛出异常:
class Hero:
yaml_tag = '!Hero'
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def to_yaml(cls, representer, data):
return representer.represent_mapping(cls.yaml_tag,
{'name': data.name, 'age': data.age})
@classmethod
def from_yaml(cls, constructor, node):
print(node) # for debug
value = constructor.construct_mapping(node)
return cls(**value)
通过标有 243 def check_mapping_key(self, node, key_node, mapping, key, value):
244 # type: (Any, Any, Any, Any, Any) -> None
--> 245 if key in mapping:
246 if not self.allow_duplicate_keys:
247 args = [
TypeError: argument of type 'NoneType' is not iterable
的{{1}}行,加载的节点为:
print(node)
此示例是显示问题的最小案例,在实际情况下,我试图仅转储部分对象,例如
for debug
MappingNode(tag='!Hero', value=[(ScalarNode(tag='tag:yaml.org,2002:str', value='name'), ScalarNode(tag='tag:yaml.org,2002:str', value='Saber')), (ScalarNode(tag='tag:yaml.org,2002:str', value='age'), ScalarNode(tag='tag:yaml.org,2002:int', value='15'))])
所需的YAML文件是
class A:
yaml_tag = '!A'
def __init__(self, name, age):
self.data = {'name': name, 'age': age}
我不知道在这种情况下如何使默认的转储器/加载器工作。
我的错误在哪里导致失败?如何解决这个问题呢?
答案 0 :(得分:0)
pandas 0.22.0
的定义是::
RoundTripConstructor.construct_mapping
,它需要知道期望进行哪种映射
构造。在RoundTripDumper中有一些期望
可以附加到这样的对象上,因此您最好模拟一下
RoundTripDumper传递中的例程:def construct_mapping(self, node, maptyp=None, deep=False)
(正常
CommentedMap
无法正常工作。
因此,您需要执行以下操作:
dict
给出:
from ruamel.yaml import YAML
from ruamel.yaml.comments import CommentedMap
yaml = YAML()
class Hero:
yaml_tag = '!Hero'
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def to_yaml(cls, representer, data):
return representer.represent_mapping(cls.yaml_tag,
{'name': data.name, 'age': data.age})
@classmethod
def from_yaml(cls, constructor, node):
data = CommentedMap()
constructor.construct_mapping(node, data, deep=True)
return cls(**data)
def __str__(self):
return "Hero(name -> {}, age -> {})".format(self.name, self.age)
yaml.register_class(Hero)
ante_hero = Hero('Saber', 15)
with open('config.yml', 'w') as fout:
yaml.dump(ante_hero, fout)
with open('config.yml') as fin:
post_hero = yaml.load(fin)
print(post_hero)
以上方法之所以有效,是因为您的课程相对简单(如果可以的话) 递归部分,您需要遵循两步创建过程, 具有创建的对象的初始产量,以便可以在递归期间使用它。
Hero(name -> Saber, age -> 15)
默认为maptyp
是历史的,它必须是
组。例如。 None
做的第一件事是
尝试附加注释(如果该节点上有注释)。
我将在0.15.55中删除默认值,这样会更明智
如果您将其遗漏,则会出现错误。