[英]How can I add a python tuple to a YAML file using pyYAML?
标题是不言自明的。
当我将元组保存到 YAML 文件时,我得到如下所示的内容:
ambient: !!python/tuple [0.3, 0.3 ,0.3]
当我尝试使用 yaml.safe_load(file_object) 加载它时,我不断收到一个错误消息:
yaml.constructor.ConstructorError: could not determine a constructor for the tag 'tag:yaml.org,2002:python/tuple'
需要做什么?
在 pyyaml 中,SafeLoader 不包含用于 Python 本机类型的加载器,仅包含 yaml 规范中定义的类型。 您可以在下面的交互示例中看到SafeLoader
和Loader
的类型。
您可以定义一个新的 Loader 类来添加 python 元组,但不能定义其他类型,因此它应该仍然非常安全:
import yaml
class PrettySafeLoader(yaml.SafeLoader):
def construct_python_tuple(self, node):
return tuple(self.construct_sequence(node))
PrettySafeLoader.add_constructor(
u'tag:yaml.org,2002:python/tuple',
PrettySafeLoader.construct_python_tuple)
doc = yaml.dump(tuple("foo bar baaz".split()))
print repr(doc)
thing = yaml.load(doc, Loader=PrettySafeLoader)
print thing
导致:
'!!python/tuple [foo, bar, baaz]\n'
('foo', 'bar', 'baaz')
有关与 SafeLoader 和 Loader 类关联的构造函数,请参见下文。
>>> yaml.SafeLoader.yaml_constructors
{None: <unbound method SafeConstructor.construct_undefined>,
u'tag:yaml.org,2002:binary': <unbound method SafeConstructor.construct_yaml_binary>,
u'tag:yaml.org,2002:bool': <unbound method SafeConstructor.construct_yaml_bool>,
u'tag:yaml.org,2002:float': <unbound method SafeConstructor.construct_yaml_float>,
u'tag:yaml.org,2002:int': <unbound method SafeConstructor.construct_yaml_int>,
u'tag:yaml.org,2002:map': <unbound method SafeConstructor.construct_yaml_map>,
u'tag:yaml.org,2002:null': <unbound method SafeConstructor.construct_yaml_null>,
u'tag:yaml.org,2002:omap': <unbound method SafeConstructor.construct_yaml_omap>,
u'tag:yaml.org,2002:pairs': <unbound method SafeConstructor.construct_yaml_pairs>,
u'tag:yaml.org,2002:seq': <unbound method SafeConstructor.construct_yaml_seq>,
u'tag:yaml.org,2002:set': <unbound method SafeConstructor.construct_yaml_set>,
u'tag:yaml.org,2002:str': <unbound method SafeConstructor.construct_yaml_str>,
u'tag:yaml.org,2002:timestamp': <unbound method SafeConstructor.construct_yaml_timestamp>}
>>> yaml.Loader.yaml_constructors
{None: <unbound method SafeConstructor.construct_undefined>,
u'tag:yaml.org,2002:binary': <unbound method SafeConstructor.construct_yaml_binary>,
u'tag:yaml.org,2002:bool': <unbound method SafeConstructor.construct_yaml_bool>,
u'tag:yaml.org,2002:float': <unbound method SafeConstructor.construct_yaml_float>,
u'tag:yaml.org,2002:int': <unbound method SafeConstructor.construct_yaml_int>,
u'tag:yaml.org,2002:map': <unbound method SafeConstructor.construct_yaml_map>,
u'tag:yaml.org,2002:null': <unbound method SafeConstructor.construct_yaml_null>,
u'tag:yaml.org,2002:omap': <unbound method SafeConstructor.construct_yaml_omap>,
u'tag:yaml.org,2002:pairs': <unbound method SafeConstructor.construct_yaml_pairs>,
u'tag:yaml.org,2002:python/bool': <unbound method Constructor.construct_yaml_bool>,
u'tag:yaml.org,2002:python/complex': <unbound method Constructor.construct_python_complex>,
u'tag:yaml.org,2002:python/dict': <unbound method Constructor.construct_yaml_map>,
u'tag:yaml.org,2002:python/float': <unbound method Constructor.construct_yaml_float>,
u'tag:yaml.org,2002:python/int': <unbound method Constructor.construct_yaml_int>,
u'tag:yaml.org,2002:python/list': <unbound method Constructor.construct_yaml_seq>,
u'tag:yaml.org,2002:python/long': <unbound method Constructor.construct_python_long>,
u'tag:yaml.org,2002:python/none': <unbound method Constructor.construct_yaml_null>,
u'tag:yaml.org,2002:python/str': <unbound method Constructor.construct_python_str>,
u'tag:yaml.org,2002:python/tuple': <unbound method Constructor.construct_python_tuple>,
u'tag:yaml.org,2002:python/unicode': <unbound method Constructor.construct_python_unicode>,
u'tag:yaml.org,2002:seq': <unbound method SafeConstructor.construct_yaml_seq>,
u'tag:yaml.org,2002:set': <unbound method SafeConstructor.construct_yaml_set>,
u'tag:yaml.org,2002:str': <unbound method SafeConstructor.construct_yaml_str>,
u'tag:yaml.org,2002:timestamp': <unbound method SafeConstructor.construct_yaml_timestamp>}
对于那些正在寻找最新答案的人。
目前,这个问题可以通过使用yaml.FullLoader
来解决。
import yaml
yaml_file = open("path/to/filename.yaml", 'r')
loaded_yaml = yaml.load(yaml_file, Loader=yaml.FullLoader)
然后标记为如下元组的条目将被正确解析而不会出现任何问题。
!!python/tuple [0.3, 0.3 ,0.3]
至少根据PyYAML 文档:
函数 yaml.safe_load 将此功能限制为简单的 Python 对象,如整数或列表。
正如您在源代码中看到的那样,该列表更加广泛,但不包括tag:yaml.org,2002:python/tuple
。
看来,如果您在 YAML 文件中生成!!python/tuple
类型,则您使用的是dump()
而不是safe_dump()
。 如果是这种情况,您可能应该切换到使用load()
代替safe_load()
,因为dump()
创建的文件不能保证可以被safe_load()
加载。 (请参阅safe_dump()
的描述)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.