YAML in Python: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
Line 21: Line 21:
<font color=darkkhaki>To install, see the "Installation" section from https://pyyaml.org/wiki/PyYAMLDocumentation.</font>
<font color=darkkhaki>To install, see the "Installation" section from https://pyyaml.org/wiki/PyYAMLDocumentation.</font>
=Overview=
=Overview=
=Concepts=
PyYAML core model is centered on [[#Constructor|constructors]], [[#Representer|representers]] and [[#Tag|tags]].
==Constructor==
{{External|https://matthewpburruss.com/post/yaml/#defining-pyyaml-constructors-going-from-yaml-to-python}}
A constructor allows you to take a serialized YAML node and return a class instance.
==Representer==
{{External|https://matthewpburruss.com/post/yaml/#defining-pyyaml-representers-going-from-python-to-yaml}}
A representer is a function intercepts data object instances to be serialized, as part of the YAML serialization process, optionally processes them, and then messages the <code>Dumper</code> instance to create the proper serialized representation for the given data object instance, as a <code>Node</code> instance. The instance thus created is returned as result of the function, contributing to the serialization result. The representer gets the <code>Dumper</code> instance as a first argument, and the data object as the second.
<syntaxhighlight lang='py'>
def my_representer(dumper: SafeDumper, data):
  return dumper.represent_scalar()
</syntaxhighlight>
The representers are registered with <code>add_representer()</code>. Representers can be added for specific types (such as <code>str</code> or <code>int</code>), or for ???
<syntaxhighlight lang='py'>
yaml.add_representer(str, my_representer) 
</syntaxhighlight>
==Tag==
The tag uses the special character <code>!</code> preceding the tag name to label a YAML node.
A tag helps PyYAML to know which [[#Constructor|constructor]] or [[#Representer|representer]] to call.


=Deserialize YAML=
=Deserialize YAML=

Revision as of 23:44, 7 December 2022

Internal

PyYAML

https://pyyaml.org/
https://pyyaml.org/wiki/PyYAMLDocumentation
https://pypi.org/project/PyYAML/

PyYAML provides YAML serialization/deserialization in Python.

Installation

pip install pyyaml

requirements.txt:

pyyaml == 5.3.1

To install, see the "Installation" section from https://pyyaml.org/wiki/PyYAMLDocumentation.

Overview

Concepts

PyYAML core model is centered on constructors, representers and tags.

Constructor

https://matthewpburruss.com/post/yaml/#defining-pyyaml-constructors-going-from-yaml-to-python

A constructor allows you to take a serialized YAML node and return a class instance.

Representer

https://matthewpburruss.com/post/yaml/#defining-pyyaml-representers-going-from-python-to-yaml

A representer is a function intercepts data object instances to be serialized, as part of the YAML serialization process, optionally processes them, and then messages the Dumper instance to create the proper serialized representation for the given data object instance, as a Node instance. The instance thus created is returned as result of the function, contributing to the serialization result. The representer gets the Dumper instance as a first argument, and the data object as the second.

def my_representer(dumper: SafeDumper, data):
  return dumper.represent_scalar()

The representers are registered with add_representer(). Representers can be added for specific types (such as str or int), or for ???

yaml.add_representer(str, my_representer)

Tag

The tag uses the special character ! preceding the tag name to label a YAML node. A tag helps PyYAML to know which constructor or representer to call.

Deserialize YAML

import yaml

with open('some-file.yaml', 'rt') as f:
  content = f.read()
data = yaml.load(content, Loader=yaml.Loader)

Serialize YAML

Serializing YAML with PyYAML
import yaml

# with the default flow style, the document is rendered in a non-indented manner 
print (yaml.dump(data, default_flow_style=False))

YAML Serialization Configuration

Safely Navigate a Complex Data Structure

Suggestions on how to safely recursively navigate a complex data structure:

Safely Navigate a Complex Data Structure

Representers

Configure yaml.dump() to render blank instead of null

PyYAML dump() uses Representer() to represent None. By default, the representer dump() is configured with represents None as "null". To change that:

1. Define a method that "represents" None

def representer_for_none(self, _):
    return self.represent_scalar('tag:yaml.org,2002:null', '')

2. Add it to the module:

import yaml

[...]

yaml.add_representer(type(None), represent_none)

This will render:

d = {
    'a': None,
    'b': 'c'
}

as:

a:
b: c

what is the lifecycle of the method registered to the module?

Configure yaml.dump() to render | multi-lines

def literal_presenter(dumper, data):
    return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')

def default_presenter(dumper, data):
     return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='')

try:
   yaml.add_representer(str, literal_presenter)
   yaml_text = yaml.dump(config)
   return yaml_text
finally:
    yaml.add_representer(str, default_presenter)