302 — Managing YAML Configuration Files

Intermediate

Install PyYAML and use yaml.safe_load() and yaml.dump() to read, write, and update YAML config files — the format used by Docker Compose, Kubernetes manifests, and GitHub Actions workflows. Learn why yaml.safe_load() is always required and why bare yaml.load() is a security risk you must avoid.

Learning Objectives

1
Install PyYAML and create a YAML config file that uses anchors and merge keys
2
Read a YAML file into a Python dict with yaml.safe_load()
3
Understand why yaml.safe_load() is always required and why bare yaml.load() is a security risk
4
Serialize a Python dict to a YAML string with yaml.dump()
5
Write YAML to a file using yaml.dump() with a stream argument
6
Update a YAML config file in place with a read-modify-write pattern
7
Catch yaml.YAMLError to handle malformed or missing YAML config files without crashing
8
Build yaml_config.py: a CLI tool that reads .yaml and .json config files based on file extension
Step 1

Set up the lesson 302 workspace, install PyYAML, and create a YAML config file

Create the lesson-302 directory, activate the virtual environment, install PyYAML, and write a `deploy.yaml` file that demonstrates YAML anchors and merge keys. This is the YAML equivalent of the `deploy.json` from lesson 301.

Commands to Run

mkdir -p ~/devops-python/lesson-302
cd ~/devops-python/lesson-302
source ~/devops-python/lesson-101/devops-env/bin/activate
pip install "PyYAML>=6,<7"
pip show PyYAML | grep -E 'Name|Version'

Files for This Step

deploy.yamlPaste this into the file
app_name: devops-app
version: "1.4.0"

# YAML anchor: define a reusable defaults block
defaults: &defaults
  port: 8080
  debug: false
  health_check: /health
  replicas: 2

environments:
  dev:
    <<: *defaults
    host: dev.example.internal
    debug: true
    replicas: 1
  staging:
    <<: *defaults
    host: staging.example.internal
  prod:
    <<: *defaults
    host: app.example.com
    port: 443
    replicas: 5

notify_on_failure:
  - ops@example.com
  - platform@example.com

After Saving

python3 -c "import yaml; data = yaml.safe_load(open('deploy.yaml')); print(type(data)); print(list(data.keys()))"

What This Does

PyYAML is not part of the Python standard library, so it must be installed with pip.

The version pin PyYAML>=6,<7 locks to the current stable series with improved security defaults.

YAML anchors (&defaults) define a reusable block that can be referenced elsewhere in the same file.

The merge key (<<: *defaults) copies every key from the anchored block into the current mapping, and local keys override the merged ones — dev overrides debug: true and replicas: 1 while inheriting port, health_check, and the default replicas from &defaults.

PyYAML's yaml.safe_load() resolves anchors and merge keys automatically, so the returned Python dict contains fully expanded values with no trace of anchor syntax.

Expected Outcome

pip outputs Name: PyYAML and Version: 6.x.

The one-liner prints <class 'dict'> and ['app_name', 'version', 'defaults', 'environments', 'notify_on_failure'] — confirming the file parsed and the top-level keys including defaults are accessible.

Pro Tips

  • 1
    PyYAML is one of the most widely installed Python packages. Run `pip show PyYAML` before installing — it may already be present as a transitive dependency of another tool in your venv.
  • 2
    The `defaults` block remains a top-level key in the parsed dict even after anchors are resolved. If you do not want it appearing in resolved configs, place it under a conventionally ignored prefix like `x-defaults: &defaults` (common in Docker Compose files).
Was this step helpful?

All Steps (0 / 8 completed)