Python:
Working with YAML

How to:

Reading and writing YAML in Python typically involves the use of a third-party library, with PyYAML being the most popular. To get started, you’ll need to install PyYAML by running pip install PyYAML.

Example: Writing to a YAML File

import yaml

data = {'a list': [1, 42, 3.141, 1337, 'help', u'€'],
        'a string': 'boo!',
        'another dict': {'foo': 'bar', 'key': 'value', 'the answer': 42}}

with open('example.yaml', 'w') as f:
    yaml.dump(data, f, default_flow_style=False)

# This creates `example.yaml` with the data structured in YAML format.

Example: Reading from a YAML File

import yaml

with open('example.yaml', 'r') as f:
    data_loaded = yaml.safe_load(f)

print(data_loaded)

# Output: 
# {'a list': [1, 42, 3.141, 1337, 'help', '€'],
#  'a string': 'boo!',
#  'another dict': {'foo': 'bar', 'key': 'value', 'the answer': 42}}

Using YAML for Configuration

Many programmers use YAML to manage application configurations. Here’s an example of how one might structure a config file and read it:

config.yaml:

database:
  host: localhost
  port: 5432
  username: admin
  password: secret

Reading the config file in Python:

import yaml

with open('config.yaml', 'r') as f:
    config = yaml.safe_load(f)

print(config['database']['host'])  # Output: localhost

Handling Complex Structures

For complex structures, PyYAML allows you to define custom Python objects. However, ensure safe practices by using safe_load to avoid executing arbitrary functions or objects.

import yaml

# Define a Python object
class Example:
    def __init__(self, value):
        self.value = value

# Custom constructor
def constructor_example(loader, node):
    value = loader.construct_scalar(node)
    return Example(value)

# Add constructor for the tag "!example"
yaml.add_constructor('!example', constructor_example)

yaml_str = "!example 'data'"
loaded = yaml.load(yaml_str, Loader=yaml.FullLoader)

print(loaded.value)  # Output: data

In this snippet, !example is a custom tag used to instantiate an Example object with the value ‘data’ from a YAML string. Custom loaders like this expand the flexibility of PyYAML, enabling the processing of more complex data structures and types.