Python Tutorial: Logging Basics - Logging to Files, Setting Levels, and Formatting
Based on Corey Schafer's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
Python’s logging module is built in, so it can replace print statements without extra installation.
Briefing
Python’s built-in logging module is presented as a practical upgrade from print statements: it lets developers capture what happened (including errors and operational details) over time, route messages by severity, and store them in files for later review or analysis.
The walkthrough starts with a simple arithmetic script that previously relied on commented-out print statements to verify results. Replacing those prints with logging calls demonstrates the first key behavior: logging levels act as a filter. Python provides five standard levels—DEBUG, INFO, WARNING, ERROR, and CRITICAL. DEBUG is detailed diagnostic information, INFO confirms normal operation, WARNING signals something unexpected but not necessarily fatal, ERROR indicates a serious failure, and CRITICAL represents an error severe enough that the program may not continue.
By default, Python’s logging level is WARNING, meaning DEBUG and INFO messages are silently ignored. When the script switches from print to logging.debug, nothing appears in the console until the configuration is changed. The fix is to set the global logging threshold using logging.basicConfig(level=logging.DEBUG). After that, the same debug calls begin to show up.
The next step moves from console output to persistent records. Instead of relying on the default console behavior, the configuration adds a file target via logging.basicConfig(..., filename='test_log'). Running the script creates (or updates) the log file, and repeated runs append new entries—making it possible to track behavior across executions rather than only observing a single run’s console output.
Formatting is then treated as a second major control knob. The log file initially includes extra fields such as the level name and logger name. To customize what appears, the configuration adds a format string using logging “special values” from Python’s logging documentation. The example narrows the output to human-readable time, the level name, and the message, producing entries like a timestamp followed by “DEBUG” and the logged text.
To show how these ideas carry into real code structure, the tutorial briefly applies logging to an object-oriented example with an Employee class. The script configures logging.basicConfig with a different file (employee log), sets level=logging.INFO, and uses a format that includes the level name and message. Replacing a print statement inside the Employee constructor with logging.info results in no console output (because INFO is filtered only if the level is higher), but the employee creation events appear in the employee log file with the chosen formatting.
The closing takeaway is that basic logging is a strong starting point for small applications, but multi-module projects introduce complications: multiple modules may share the same logger, leading to configuration conflicts. The next lesson is positioned around creating separate loggers, adding handlers and formatters, and sending logs to multiple destinations.
Cornell Notes
Logging in Python replaces ad-hoc print debugging with structured, level-based messages that can be filtered and persisted. Python’s standard levels—DEBUG, INFO, WARNING, ERROR, and CRITICAL—control what gets emitted; the default threshold is WARNING, so DEBUG/INFO won’t show unless the level is lowered. logging.basicConfig can route output to the console or to a file (e.g., test_log, employee log), and it can also change the log line layout using a format string (such as time, level name, and message). Applying logging to an Employee class shows how INFO messages can be recorded without cluttering the console, while still capturing events across runs.
Why do DEBUG and INFO messages appear to “disappear” when switching from print to logging?
How does logging.basicConfig change where log messages go and how they’re recorded?
What’s the practical difference between changing the logging level in code vs. changing the logging call itself?
How can log output be reformatted to include only the most useful fields?
How does the Employee class example demonstrate logging in a real code path?
Review Questions
- What happens to DEBUG and INFO log calls when logging.basicConfig is left at its default settings?
- How would you configure logging to write INFO and above messages to a file named app.log with a format that includes time and the message?
- Why can basic logging become problematic when multiple modules are imported into a larger project?
Key Points
- 1
Python’s logging module is built in, so it can replace print statements without extra installation.
- 2
Logging levels (DEBUG, INFO, WARNING, ERROR, CRITICAL) determine which messages are emitted based on the configured threshold.
- 3
The default logging level is WARNING, so DEBUG and INFO messages are ignored unless the threshold is lowered.
- 4
logging.basicConfig can send logs to a file using the filename parameter, enabling persistent records across runs.
- 5
A format string in logging.basicConfig lets developers control what fields appear in each log line (e.g., time, level name, message).
- 6
In small scripts, basic logging is sufficient, but multi-module applications often require separate loggers and handlers to avoid conflicts.