During development debugging or confirming operation in a production environment, it is common to use the print() function to check “how far the program has progressed” or “what the variable values are.”
However, in full-scale application development, it is strongly recommended to use the standard library logging module instead of print().
This article explains the basic usage of the logging module, the concept of log levels, and how to set output formats.
Why logging Instead of print()?
Compared to the print() function, the logging module has the following advantages:
- Control via Log Levels: You can easily filter logs based on importance (error, warning, info, etc.). (e.g., Do not output debug information in production).
- Changing Output Destinations: You can flexibly change output destinations (handlers) not only to standard output (console) but also to saving to files or sending emails.
- Unified Format: Automatically adds metadata such as date and time, filename, and line number to unify the log format.
Understanding Log Levels
The logging module defines five log levels in order of increasing importance. Logs with a level equal to or higher than the set level are output.
| Level | Constant Name | Numeric Value | Usage |
| DEBUG | logging.DEBUG | 10 | Detailed information during development. For verifying operation. |
| INFO | logging.INFO | 20 | Reporting normal operation. Start/end of processing, etc. |
| WARNING | logging.WARNING | 30 | Unexpected but executable problem. Warning. |
| ERROR | logging.ERROR | 40 | Function cannot be executed due to a serious problem. |
| CRITICAL | logging.CRITICAL | 50 | Fatal error causing the program itself to stop. |
By default, only logs of WARNING or higher are output, and INFO and DEBUG are ignored.
Basic Implementation Example
Now, let’s write code to output logs using the logging module.
Here we introduce the standard pattern: using basicConfig for overall log settings and obtaining a module-specific logger with getLogger(__name__).
import logging
# 1. Basic Log Configuration
# level: Specify the minimum level to output (INFO or higher here)
# format: Specify log output format (Time - Logger Name - Level - Message)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
# 2. Get Logger
# Passing __name__ makes it easier to identify which module the log came from
logger = logging.getLogger(__name__)
def perform_task(task_id):
# Info Level Log (Will be output)
logger.info(f"Starting process for Task {task_id}.")
# Debug Level Log (Will NOT be output because setting is INFO)
logger.debug(f"Detailed debug info for Task {task_id}...")
if task_id < 0:
# Error Level Log (Will be output)
logger.error("Invalid Task ID. Aborting process.")
return
# Warning Level Log (Will be output)
if task_id > 1000:
logger.warning("Task ID is too large. Processing may take time.")
logger.info(f"Task {task_id} completed.")
# --- Execution ---
print("--- Execute Process ---")
perform_task(10)
print("\n--- Error Case ---")
perform_task(-1)
Output:
--- Execute Process ---
2025-11-29 10:30:05,123 - __main__ - INFO - Starting process for Task 10.
2025-11-29 10:30:05,123 - __main__ - INFO - Task 10 completed.
--- Error Case ---
2025-11-29 10:30:05,124 - __main__ - INFO - Starting process for Task -1.
2025-11-29 10:30:05,124 - __main__ - ERROR - Invalid Task ID. Aborting process.
Explanation of the Code
logging.basicConfig(...): Performs initial configuration of the logging system. Sincelevel=logging.INFOwas set, the content oflogger.debug()was not output.format="...": Specifies the log output format.%(asctime)s: Date and Time%(name)s: Logger name (here__name__, so__main__)%(levelname)s: Log level name (INFO, ERROR, etc.)%(message)s: Log message body
logging.getLogger(__name__): Creates a logger object. It is customary to pass the module name (__name__) as an argument. This clarifies which file the log originated from.
Outputting Logs to a File (Handler)
If you want to save to a file instead of displaying on the screen, simply add the filename argument to basicConfig.
logging.basicConfig(
filename="app.log", # Output file name
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
When you run this, nothing will be displayed on the console; instead, an app.log file will be created in the execution directory, and logs will be appended to it.
Summary
- Use the
loggingmodule instead ofprint()for log output. - Distinguish between the 5 log levels (DEBUG, INFO, WARNING, ERROR, CRITICAL).
- Use
logging.basicConfig()to batch set levels and formats. - Create a logger instance with
logger = logging.getLogger(__name__)and use it.
