Getting Started with Python's Logging Module
Learn why and how to use Python's built-in logging module instead of print statements. This guide covers log levels, formatting, real-world examples, and common pitfalls.
Getting Started with Python's Logging Module: A Practical Guide
If you've ever spent hours trying to debug a Python script by scattering print() statements everywhere, you know the pain. At PythonSkillset, we believe that understanding logging early can save you countless headaches and make your code truly production-ready.
Logging in Python isn't just about printing messages—it's about controlling what gets printed, where it goes, and when. The built-in logging module is incredibly powerful once you get past the initial learning curve.
Why Not Just Use print()?
Let's face it—we've all done it. Adding a quick print() to see what's happening in our code feels natural. But here's the problem: you eventually have to remove or comment out all those print statements. And when your application runs in production, you need different information than during development.
Logging gives you: - Different severity levels (debug, info, warning, error, critical) - Control over output (console, files, network) - Format control (timestamps, line numbers, module names) - Runtime configuration (change log levels without modifying code)
Setting Up Your First Logger
Let's start with the simplest possible setup. At PythonSkillset, we recommend beginning with a basic configuration and then building up from there.
import logging
# Basic configuration
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# Create a logger
logger = logging.getLogger(__name__)
# Log some messages
logger.debug("This is a debug message") # Won't appear because level is INFO
logger.info("Application started successfully")
logger.warning("Disk space is running low")
logger.error("Failed to connect to database")
logger.critical("System is shutting down")
When you run this, you'll see only the INFO, WARNING, ERROR, and CRITICAL messages. The DEBUG message is silenced because we set the level to INFO.
Understanding Log Levels
Python's logging has five standard levels, each with a numeric value:
| Level | Numeric Value | When to Use |
|---|---|---|
| DEBUG | 10 | Detailed diagnostic information |
| INFO | 20 | Confirmation that things are working |
| WARNING | 30 | Something unexpected happened, but application continues |
| ERROR | 40 | A serious problem, but application continues |
| CRITICAL | 50 | A serious error, application may stop |
The rule is simple: only messages at level >= the configured level will appear. This lets you filter noise during development and switch to more verbose logging when troubleshooting.
Adding Logging to a Real Application
Let's build something practical. Imagine you're working on a data processing pipeline for PythonSkillset's analytics system:
import logging
from datetime import datetime
# Configure logging for our application
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
filename='app.log' # Write to file
)
logger = logging.getLogger('DataProcessor')
def process_user_data(user_data):
logger.info(f"Processing data for user {user_data.get('id')}")
try:
# Simulate processing
if not user_data.get('email'):
logger.warning(f"User {user_data.get('id')} has no email address")
# More processing...
logger.debug(f"User data: {user_data}") # Won't show in file
return True
except Exception as e:
logger.error(f"Failed to process user {user_data.get('id')}: {str(e)}")
return False
# Test it
users = [
{"id": 1, "email": "user1@example.com"},
{"id": 2, "email": None},
{"id": 3, "email": "user3@example.com"}
]
for user in users:
process_user_data(user)
Now check app.log—you'll see a clean, timestamped record of what happened. No more hunting through terminal output.
Formatting Your Logs
Good formatting makes logs readable and searchable. Here's what each format placeholder means:
%(asctime)s- Human-readable time%(name)s- Logger name (usually__name__)%(levelname)s- Log level (INFO, ERROR, etc.)%(message)s- The actual message%(filename)s- File where log was called%(lineno)d- Line number%(funcName)s- Function name
A practical format for production might be:
logging.basicConfig(
format='%(asctime)s | %(levelname)-8s | %(filename)s:%(lineno)d | %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
Common Pitfalls to Avoid
After working with many Python developers at PythonSkillset, here are the mistakes we see most often:
- Using the root logger directly - Don't call
logging.info(). Create your own logger withgetLogger(__name__). - Forgetting to set log levels - Without configuration, logging defaults to WARNING, so your INFO messages vanish.
- Logging sensitive information - Passwords, API keys, and personal data should never appear in logs.
- Over-logging in loops - Inside tight loops, use DEBUG level instead of INFO to avoid bloating your logs.
When to Use Each Level
Here's a rule of thumb that we follow at PythonSkillset:
- DEBUG: Variable values, function entry/exit points, API call details
- INFO: Application start/stop, successful operations, user actions
- WARNING: Deprecated functions, low disk space, temporary failures
- ERROR: Failed database connections, API errors, corrupted data
- CRITICAL: System out of memory, security breaches, unrecoverable errors
Moving Forward
Once you've mastered basic logging, you can explore advanced features like: - Multiple handlers (console + file simultaneously) - Log rotation (automatically archive old logs) - Custom formatters - Child loggers for different modules
The key takeaway? Start small. Add logging to one module today. Tomorrow, you'll wonder how you ever lived without it. At PythonSkillset, we've seen this simple practice transform debugging from a frustrating chore into a straightforward process.
Your future self—the one trying to figure out why production code failed at 3 AM—will thank you.
Comments
Questions, corrections, and tips stay visible for everyone reading this page.
Join the discussion
No comments yet
Be the first to leave a note — it helps the next reader.