Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
100: Working with YAML Files
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.yamlwith the following initial data:api_url: "https://api.example.com"timeout: 30retries: 3
- Write a Python script that:
- Loads the
app_config.yamlfile using the secure loading method. - Changes the
timeoutvalue to 60 and adds a new keydebug_modeset toTrue. - Saves the updated configuration back to the file, ensuring it uses the clean, indented block style (no flow style).
- Loads the
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.
There are no comments for now.