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

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-05 05:16:10

In pyyaml, the SafeLoader does not include a loader for the python native types, only the types defined in the yaml spec. You can see the types for the SafeLoader and the Loader here in the interaction sample below.

You can define a new Loader class that adds in the python tuple, but not other types, so it should still be pretty safe:

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.

>>> 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>}
ig0774

At least according to the PyYAML documentation:

The function yaml.safe_load limits this ability to simple Python objects like integers or lists.

The list, as you can see in the source, is somewhat more extensive but does not include 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(). 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(). (See the description of safe_dump()).

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!