Skip to Content
Course content

100: Working with YAML Files

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Whenever I see a junior dev start working with YAML, they usually tell me the same thing: "It's just JSON without the curly braces, right? I'll just use a library to parse it and it'll be exactly like a Python dictionary."

Thinking YAML is just "JSON without the Brackets"

On the surface, that's mostly true. YAML is designed to be human-readable, and for 90% of your config files, it behaves exactly like a nested dictionary. But there is a massive, dangerous difference under the hood. Unlike JSON, YAML allows for "tags" that can tell the parser to instantiate actual Python objects during the loading process.

If you use the standard yaml.load() function on a file you didn't write yourself, you aren't just loading data—you're potentially executing code. I've seen this bite people in production. Look at this snippet:

import yaml

# Imagine this string came from an external API or a user-uploaded config
malicious_yaml = "!!python/object/apply:os.system ['echo I just ran a shell command on your machine!']"

# This looks innocent, but it's a security nightmare
data = yaml.load(malicious_yaml, Loader=yaml.Loader) 

If you run that, you'll see the echo command execute in your terminal. The parser saw the !!python/object/apply tag and decided to actually call os.system(). This is why yaml.load() is considered unsafe and why you'll see a lot of warnings about it in older StackOverflow threads.

Why safe_load() is your only real option

In the real world, you should almost never use yaml.load(). Instead, use yaml.safe_load(). This restricts the parser to simple Python objects—strings, integers, lists, and dictionaries—and ignores those dangerous custom tags. It turns the parser back into the "JSON-like" tool you expected it to be.

Let's look at a proper way to handle a configuration file for a hypothetical game project. I prefer keeping my settings in YAML because it allows for comments, which JSON stubbornly refuses to support.

import yaml

# Let's assume we have a 'settings.yaml' file with this content:
# player_name: "Cipher"
# difficulty: "Hard"
# inventory:
#   - "Health Potion"
#   - "Iron Sword"

with open('settings.yaml', 'r') as file:
    # safe_load ensures no one can sneak a system call into our config file
    config = yaml.safe_load(file)

print(f"Loading game for {config['player_name']}...")
print(f"Starting item: {config['inventory'][0]}")

Turning Python Dicts back into YAML

Reading is the easy part. Writing YAML (called "dumping") is where things can get messy. If you just call yaml.dump(), the library sometimes adds weird tags like !!python/tuple to your file to ensure it can be reconstructed exactly. It makes the file ugly and harder for humans to read.

To keep your output clean and "standard," I always recommend using default_flow_style=False. This forces the library to use the indented block style we all love, rather than switching back to JSON-like brackets for nested lists.

import yaml

game_state = {
    'level': 12,
    'bosses_defeated': ['Goblin King', 'Shadow Wraith'],
    'stats': {
        'strength': 15,
        'agility': 22
    }
}

with open('savegame.yaml', 'w') as file:
    yaml.dump(game_state, file, default_flow_style=False)

Now, your savegame.yaml looks professional and clean, rather than a chaotic mix of brackets and indentation.




📋 Practical Task

Build a YAML-based App Configuration Manager

You are building a CLI tool that requires a configuration file to define API endpoints and timeout settings. Your goal is to create a script that can both load an existing config and update it programmatically.

Requirements:

  • Create a file named app_config.yaml with the following initial data:
    • api_url: "https://api.example.com"
    • timeout: 30
    • retries: 3
  • Write a Python script that:
    1. Loads the app_config.yaml file using the secure loading method.
    2. Changes the timeout value to 60 and adds a new key debug_mode set to True.
    3. Saves the updated configuration back to the file, ensuring it uses the clean, indented block style (no flow style).

Verification: After running your script, open app_config.yaml in a text editor to confirm the values are updated and the formatting is clean and human-readable.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.