简体   繁体   English

如何使用 pyYAML 将 python 元组添加到 YAML 文件?

[英]How can I add a python tuple to a YAML file using pyYAML?

The title is fairly self-explanatory.标题是不言自明的。

When I save a tuple to a YAML file, I get something that looks like this:当我将元组保存到 YAML 文件时,我得到如下所示的内容:

ambient:  !!python/tuple [0.3, 0.3 ,0.3]

When I try to load it with yaml.safe_load(file_object), I keep getting an error that reads:当我尝试使用 yaml.safe_load(file_object) 加载它时,我不断收到一个错误消息:

yaml.constructor.ConstructorError:  could not determine a constructor for the tag 'tag:yaml.org,2002:python/tuple'

What needs to be done?需要做什么?

In pyyaml, the SafeLoader does not include a loader for the python native types, only the types defined in the yaml spec.在 pyyaml 中,SafeLoader 不包含用于 Python 本机类型的加载器,仅包含 yaml 规范中定义的类型。 You can see the types for the SafeLoader and the Loader here in the interaction sample below.您可以在下面的交互示例中看到SafeLoaderLoader的类型。

You can define a new Loader class that adds in the python tuple, but not other types, so it should still be pretty safe:您可以定义一个新的 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

resulting in:导致:

'!!python/tuple [foo, bar, baaz]\n'
('foo', 'bar', 'baaz')

See below for the constructors associated with the SafeLoader and the Loader classes.有关与 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>}

For those, who are looking for an up-to-date answer.对于那些正在寻找最新答案的人。

Currently, this issue can be solved by using yaml.FullLoader .目前,这个问题可以通过使用yaml.FullLoader来解决。

import yaml
yaml_file = open("path/to/filename.yaml", 'r')
loaded_yaml = yaml.load(yaml_file, Loader=yaml.FullLoader)

Then entries marked as tuples as below will be correctly parsed without any issues.然后标记为如下元组的条目将被正确解析而不会出现任何问题。

!!python/tuple [0.3, 0.3 ,0.3]

At least according to the PyYAML documentation :至少根据PyYAML 文档

The function yaml.safe_load limits this ability to simple Python objects like integers or lists.函数 yaml.safe_load 将此功能限制为简单的 Python 对象,如整数或列表。

The list, as you can see in the source , is somewhat more extensive but does not include tag:yaml.org,2002:python/tuple . 正如您在源代码中看到的那样,该列表更加广泛,但不包括tag:yaml.org,2002:python/tuple

It appears that if you are generating a !!python/tuple type in your YAML file, you are using dump() as opposed to safe_dump() .看来,如果您在 YAML 文件中生成!!python/tuple类型,则您使用的是dump()而不是safe_dump() If that's the case, you should probably switch to using load() in place of safe_load() , as files created by dump() are not guaranteed to be loadable by safe_load() .如果是这种情况,您可能应该切换到使用load()代替safe_load() ,因为dump()创建的文件不能保证可以被safe_load()加载。 (See the description of safe_dump() ). (请参阅safe_dump()描述)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM