将 YAML 反序列化回 Python 对象
Deserializing YAML back into Python object
我正在尝试为我的 class 编写一个正确的 from_yaml
方法,以便在使用 ruamel.yaml
库加载 YAML 文件时能够反序列化回它。
让我们假设在我的 to_yaml
class 方法中我返回类似的东西:
@classmethod
def to_yaml(cls, dumper, data):
dict_representation = {
'foo': data.foo,
'bar': data.bar
}
return dumper.represent_mapping(cls.yaml_tag, dict_representation)
现在在反序列化方法中
@classmethod
def from_yaml(cls, constructor, node):
dict_representation = constructor.construct_mapping(node, deep=True)
有了这个我得到了 TypeError
:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-6-782b00e19bec> in <module>()
----> 1 dict_representation = yaml.constructor.construct_mapping(node, deep=True)
/home/**/.envs/myenv/local/lib/python2.7/site-packages/ruamel/yaml/constructor.pyc in construct_mapping(self, node, maptyp, deep)
1186 "found unhashable key", key_node.start_mark)
1187 value = self.construct_object(value_node, deep=deep)
-> 1188 self.check_mapping_key(node, key_node, maptyp, key, value)
1189
1190 if key_node.comment and len(key_node.comment) > 4 and \
/home/**/.envs/myenv/local/lib/python2.7/site-packages/ruamel/yaml/constructor.pyc in check_mapping_key(self, node, key_node, mapping, key, value)
241 def check_mapping_key(self, node, key_node, mapping, key, value):
242 # type: (Any, Any, Any, Any, Any) -> None
--> 243 if key in mapping:
244 if not self.allow_duplicate_keys:
245 args = [
TypeError: argument of type 'NoneType' is not iterable
事实上,在交互式 shell:
中尝试更凭经验地做到这一点
import ruamel.yaml
yaml = ruamel.yaml.YAML()
dd = {'foo': 'foo'}
node = yaml.representer.represent_mapping('!dd', dd)
dict_representation = yaml.constructor.construct_mapping(node)
引发相同的异常。我在这里错过了什么?
为了使往返有效,RoundTripConstructor()
的 construct_mapping()
需要获取传入的实际映射类型实例,因此可以从节点中获取注释之类的东西并附加到该实例(通常是 CommentedMap()
)。执行非往返加载时不需要该额外参数(因为不需要传递评论信息)。
该方法本可以设计得更智能,因为目前如果未提供默认为 None 作为映射类型,这就是您从中获得 NoneType is not iterable
异常的地方。
要从问题末尾的代码开始,您可以通过以下方式调用更简单的映射构造函数:
dict_representation = ruamel.yaml.constructor.SafeConstructor.construct_mapping(
yaml.constructor, node)
您的 from_yaml()
class-方法应该以同样的方式工作:
@classmethod
def from_yaml(cls, constructor, node):
dict_representation = ruamel.yaml.constructor.SafeConstructor.construct_mapping(
constructor, node, deep=True)
尽管如果您正在构建复杂类型(其中某些可间接访问的值可能引用此节点),您应该考虑使用两步创建过程:
@classmethod
def from_yaml(cls, constructor, node):
dict_representation = dict()
yield dict_representation
d = ruamel.yaml.constructor.SafeConstructor.construct_mapping(
constructor, node, deep=True)
dict_representation.update(d)
我正在尝试为我的 class 编写一个正确的 from_yaml
方法,以便在使用 ruamel.yaml
库加载 YAML 文件时能够反序列化回它。
让我们假设在我的 to_yaml
class 方法中我返回类似的东西:
@classmethod
def to_yaml(cls, dumper, data):
dict_representation = {
'foo': data.foo,
'bar': data.bar
}
return dumper.represent_mapping(cls.yaml_tag, dict_representation)
现在在反序列化方法中
@classmethod
def from_yaml(cls, constructor, node):
dict_representation = constructor.construct_mapping(node, deep=True)
有了这个我得到了 TypeError
:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-6-782b00e19bec> in <module>()
----> 1 dict_representation = yaml.constructor.construct_mapping(node, deep=True)
/home/**/.envs/myenv/local/lib/python2.7/site-packages/ruamel/yaml/constructor.pyc in construct_mapping(self, node, maptyp, deep)
1186 "found unhashable key", key_node.start_mark)
1187 value = self.construct_object(value_node, deep=deep)
-> 1188 self.check_mapping_key(node, key_node, maptyp, key, value)
1189
1190 if key_node.comment and len(key_node.comment) > 4 and \
/home/**/.envs/myenv/local/lib/python2.7/site-packages/ruamel/yaml/constructor.pyc in check_mapping_key(self, node, key_node, mapping, key, value)
241 def check_mapping_key(self, node, key_node, mapping, key, value):
242 # type: (Any, Any, Any, Any, Any) -> None
--> 243 if key in mapping:
244 if not self.allow_duplicate_keys:
245 args = [
TypeError: argument of type 'NoneType' is not iterable
事实上,在交互式 shell:
中尝试更凭经验地做到这一点import ruamel.yaml
yaml = ruamel.yaml.YAML()
dd = {'foo': 'foo'}
node = yaml.representer.represent_mapping('!dd', dd)
dict_representation = yaml.constructor.construct_mapping(node)
引发相同的异常。我在这里错过了什么?
为了使往返有效,RoundTripConstructor()
的 construct_mapping()
需要获取传入的实际映射类型实例,因此可以从节点中获取注释之类的东西并附加到该实例(通常是 CommentedMap()
)。执行非往返加载时不需要该额外参数(因为不需要传递评论信息)。
该方法本可以设计得更智能,因为目前如果未提供默认为 None 作为映射类型,这就是您从中获得 NoneType is not iterable
异常的地方。
要从问题末尾的代码开始,您可以通过以下方式调用更简单的映射构造函数:
dict_representation = ruamel.yaml.constructor.SafeConstructor.construct_mapping(
yaml.constructor, node)
您的 from_yaml()
class-方法应该以同样的方式工作:
@classmethod
def from_yaml(cls, constructor, node):
dict_representation = ruamel.yaml.constructor.SafeConstructor.construct_mapping(
constructor, node, deep=True)
尽管如果您正在构建复杂类型(其中某些可间接访问的值可能引用此节点),您应该考虑使用两步创建过程:
@classmethod
def from_yaml(cls, constructor, node):
dict_representation = dict()
yield dict_representation
d = ruamel.yaml.constructor.SafeConstructor.construct_mapping(
constructor, node, deep=True)
dict_representation.update(d)