In this lesson, we are going to learn how to read and write YAML files in Python using the PyYAML library.

What is YAML?

As we have already learned in our lesson about this data formatting language, YAML is a recursive acronym for YAML Ain't Markup Language. It is designed to be very human-readable using only very minimal syntax such as indentation and nesting. 

YAML natively supports three main data types: scalars (such as strings, integers, and floats), lists, and associative arrays (also known as maps, dictionaries, or hashes) but can also support custom data types. The official filename extension of YAML files is .yaml

In networking, it is commonly used for configuration files that are stored and transmitted to network devices. It is the standard data formatting language used by networking tools such as Ansible and Terraform.

Reading and writing YAML files are supported by many programming languages. One of the most popular ones for parsing YAML is Python. In this tutorial, we are going to use the PyYAML library.

PyYAML module

PyYAML is an external Python module and must be installed first before we start using it. There are two ways to do it:

Method 1: Via Source

First, you go to the module's source page and download the repository as a zip file. Then, using a terminal or command prompt, we navigate to the directory where the file is downloaded and run the following command:

$ python setup.py install

Method 2: Via Pip

There is an easier way to install the YAML library in Python. If you have the package manager pip installed in your environment, you just use the following command to download and install PyYAML:

$ pip install pyyaml

Working with YAML files in Python

In this section, we will learn how to read and write YAML files, i.e. how to load and manipulate them with Python scripts.

Reading YAML Files

Let's first define our example that we are going to work with. The first file's content is as follows:

# router.yaml file

interfaces:

  - GigabitEthernet0/0
  - GigabitEthernet0/1
  - GigabitEthernet2/1
  - FastEthernet0/0/0
  - FastEthernet0/1/0
  - Serial0/0/0

prefixes:

  - 10.0.0.0/24
  - 1.2.3.0/24
  - 192.168.1.0/24
  - 172.16.12.0/22
  - 172.16.1.0/24
  - 198.54.1.0/28

The second file is as follows:

# network.yaml file

routers: 11
switches: 23
firewalls: 3
APs: 7
proxies: 1

Let's now open and read the first example file with Python script. We are going to use the load method from the PyYAML module. 

import yaml

with open('router.yaml') as file:
    # The FullLoader parameter handles the conversion
    # from YAML scalar values to Python dictionary
    interfaces = yaml.load(file, Loader=yaml.FullLoader)

    print(interfaces)

Output:

{'interfaces': [
    'GigabitEthernet0/0',
    'GigabitEthernet0/1',
    'GigabitEthernet2/1',
    'FastEthernet0/0/0',
    'FastEthernet0/1/0',
    'Serial0/0/0',
    ], 
'prefixes': [
    '10.0.0.0/24',
    '1.2.3.0/24',
    '192.168.1.0/24',
    '172.16.12.0/22',
    '172.16.1.0/24',
    '198.54.1.0/28',
    ]}

Note the Loader parameter we pass to the .load method yaml.load(file, Loader=yaml.FullLoader), it loads the full YAML language and handles the conversion of YAML scalars to Python dictionaries and lists.

IMPORTANT: It is not safe to call yaml.load with any data received from an untrusted source as it may call any Python function!

Instead of specifying the loader as an argument, we can directly use one of the following methods that indicate hot to load the YAML:

- yaml.safe_load
- yaml.full_load
- yaml.unsafe_load

Writing YAML files

In the previous section, we have learned how to read YAML files in Python. Let's now try to store a Python dictionary into a YAML file. For this purpose, we are going to use the dictionary that we have got from the reading example.

import yaml

dictionary = {'interfaces': [
    'GigabitEthernet0/0',
    'GigabitEthernet0/1',
    'GigabitEthernet2/1',
    'FastEthernet0/0/0',
    'FastEthernet0/1/0',
    'Serial0/0/0',
],
    'prefixes': [
        '10.0.0.0/24',
        '1.2.3.0/24',
        '192.168.1.0/24',
        '172.16.12.0/22',
        '172.16.1.0/24',
        '198.54.1.0/28',
    ]}

with open('interfaces.yaml', 'w') as file:
    interfaces = yaml.dump(dictionary, file)

The yaml.dump function accepts a Python dictionary as the first parameter and produces a YAML document as defined in the file object we pass as the second parameter.

Once the above code executes, it results in the following YAML file:

interfaces:
- GigabitEthernet0/0
- GigabitEthernet0/1
- GigabitEthernet2/1
- FastEthernet0/0/0
- FastEthernet0/1/0
- Serial0/0/0
prefixes:
- 10.0.0.0/24
- 1.2.3.0/24
- 192.168.1.0/24
- 172.16.12.0/22
- 172.16.1.0/24
- 198.54.1.0/28

YAML resources:

If you want to dive deeper into using YAML with Python, check out the following resources and documentations:

noyam