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
262: The tomllib Module for TOML Config Files
If you've spent any time managing project settings, you know the struggle. JSON is great for machines but a nightmare for humans to edit manually because of those trailing commas. YAML is visually clean, but one accidental space in your indentation can break your entire deployment. That's why I've shifted most of my configuration files to TOML (Tom's Obvious, Minimal Language).
Since Python 3.11, we have the tomllib module built right into the standard library. It's fast and follows the spec strictly. Today, we're going to build a small configuration loader for a hypothetical "Web Scraper" tool that needs to handle different environment settings and API keys.
Defining our Scraper Settings
First, let's create a configuration file. I prefer TOML because it handles sections (tables) beautifully. I'll create a file named settings.toml. Notice how I can group my scraping targets separately from my global app settings.
# settings.toml
[app]
debug = true
timeout = 30
log_level = "INFO"
[sources.tech_crunch]
url = "https://techcrunch.com"
max_articles = 10
[sources.wired]
url = "https://wired.com"
max_articles = 5
Pulling the Data into Python
Now, let's get this into our code. The tomllib module provides load() for file streams and loads() for strings. Since we have a file, we'll use load(). One thing to keep in mind: tomllib requires the file to be opened in binary mode ("rb"), not text mode. I've tripped over this more than once.
import tomllib
try:
with open("settings.toml", "rb") as f:
config = tomllib.load(f)
except FileNotFoundError:
print("Config file missing!")
config = {}
print(f"Debugging enabled: {config['app']['debug']}")
print(f"Wired URL: {config['sources']['wired']['url']}")
The "Write-Only" Trap
Here is where I usually hit a wall when I first start a project. I'll try to write a "reset to defaults" feature where the script updates the TOML file programmatically. I'll instinctively try something like this:
# This will fail!
import tomllib
config = {"app": {"debug": False}}
with open("settings.toml", "wb") as f:
tomllib.dump(config, f) # AttributeError: module 'tomllib' has no attribute 'dump'
I forgot that tomllib is a read-only parser. The Python maintainers decided not to include a writer in the standard library to keep the module lean. If you actually need to write TOML files, you'll have to install a third-party library like tomli-w. For this lesson, we'll stick to reading, which is 95% of what you'll do with config files anyway.
Using the Loaded Config
Now that we know we can't write back to the file, let's actually use the data to drive some logic. I like to wrap the config access in a way that provides defaults, just in case a user deletes a line from the TOML file.
import tomllib
def run_scraper(config):
# Using .get() helps avoid KeyError if the TOML is malformed
app_settings = config.get("app", {})
timeout = app_settings.get("timeout", 10) # Default to 10 seconds
sources = config.get("sources", {})
for name, data in sources.items():
print(f"Scraping {name} at {data['url']} (Max: {data['max_articles']})")
print(f"Applying timeout of {timeout}s...")
with open("settings.toml", "rb") as f:
config_data = tomllib.load(f)
run_scraper(config_data)
📋 Practical Task
Build a Multi-Environment Database Config Loader
Your task is to create a Python script that simulates loading different database credentials based on an environment variable.
- Create a file named
db_config.tomlwith two sections:[development]and[production]. Each section should have ahost,port(integer), andenabled(boolean). - Write a Python script that imports
tomllib. - The script should define a variable
env = "development"(you can manually change this to "production" to test). - Load the TOML file and use the
envvariable to access the correct section. - Print a formatted string:
"Connecting to {env} database at {host}:{port}...", but only ifenabledisTrue. IfenabledisFalse, print"Database for {env} is currently disabled."
There are no comments for now.