13

标题是不言自明的。

当我将元组保存到 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'

需要做什么?

4

3 回答 3

14

在 pyyaml 中,SafeLoader 不包含用于 python 原生类型的加载器,仅包含 yaml 规范中定义的类型。您可以在下面的交互示例中查看 theSafeLoader和here 的类型。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>}
于 2012-02-07T00:43:06.990 回答
4

至少根据PyYAML 文档

yaml.safe_load 函数将这种能力限制为简单的 Python 对象,如整数或列表。

正如您在源代码中看到的那样,该列表更为广泛,但不包括tag:yaml.org,2002:python/tuple.

看来,如果您!!python/tuple在 YAML 文件中生成类型,则您使用dump()的是与safe_dump(). 如果是这种情况,您可能应该改用 usingload()代替,因为不保证由.safe_load()创建的文件可以由. (参见 的描述)。dump()safe_load()safe_dump()

于 2012-02-07T00:40:30.043 回答
1

对于那些正在寻找最新答案的人。

目前,这个问题可以通过使用来解决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]

于 2021-06-02T14:38:08.847 回答