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

The name is pretty clear.

When I save a tuple in a YAML file, I get something similar to this:

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

When I try to download it using yaml.safe_load (file_object), I keep getting the error message:

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

What should be done?

+7
source share
2 answers

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

You can define a new Loader class that adds python to the tuple, but not other types, so it will 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 

as a result of:

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

See the constructors associated with the SafeLoader and Loader classes below.

 >>> 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>} 
+9
source

At least as per PyYAML documentation :

The yaml.safe_load function restricts this ability to simple Python objects, such as 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 looks like if you create the type !!python/tuple in your YAML file, you use dump() and not safe_dump() . In this case, you should probably switch to using load() instead of safe_load() since the files created by dump() cannot be loaded using safe_load() . (See the description of safe_dump() ).

0
source

All Articles