Logging Module
Logging Module in Python
Learn how to record application events, errors, warnings, and diagnostic information using Python's built-in logging module.
During application development, programmers need to understand what the application is doing, where an error occurred, and which operations completed successfully.
Python provides the built-in logging module for
recording application events. It supports severity levels,
formatted messages, console output, file output, named loggers,
handlers, and exception information.
Prerequisites
What You Should Know
- Python variables and data types
- Functions and modules
- Import statements
- Exception handling with try and except
- Basic file and application concepts
- String formatting
What is Logging?
Logging is the process of recording information about events that occur while an application is running.
A log record may contain a message, severity level, timestamp, logger name, module name, function name, or exception details.
Think of logging as an application diary
The application records important events as they happen. Developers can later review those records to understand application behavior and investigate failures.
Import the Logging Module
The logging module is part of Python's standard library.
import logging
Create Your First Log Message
import logging
logging.warning(
"The application is using a default configuration."
)
Possible output:
WARNING:root:The application is using a default configuration.
The output identifies the severity level, logger name, and log message.
Logging Levels
Logging levels classify records according to their importance or severity.
| Level | Typical Purpose |
|---|---|
DEBUG
|
Detailed diagnostic information used during development or investigation. |
INFO
|
Confirmation that an expected operation occurred. |
WARNING
|
An unexpected situation occurred, but processing may continue. |
ERROR
|
An operation failed or could not be completed. |
CRITICAL
|
A severe failure may prevent continued operation. |
Record Different Log Levels
import logging
logging.debug(
"Preparing diagnostic data."
)
logging.info(
"Application started successfully."
)
logging.warning(
"The configuration file was not found."
)
logging.error(
"The customer record could not be saved."
)
logging.critical(
"The application cannot continue."
)
Configure Logging with basicConfig()
Use logging.basicConfig() to define introductory
logging settings.
import logging
logging.basicConfig(
level=logging.INFO
)
logging.debug(
"Debug message"
)
logging.info(
"Application started"
)
logging.warning(
"Configuration is incomplete"
)
Possible output:
INFO:root:Application started
WARNING:root:Configuration is incomplete
The configured level allows INFO and higher-severity records to be processed.
Format Log Messages
import logging
logging.basicConfig(
level=logging.INFO,
format=(
"%(asctime)s | "
"%(levelname)s | "
"%(name)s | "
"%(message)s"
)
)
logging.info(
"Application started."
)
Possible output:
2026-08-08 10:30:15,125 | INFO | root | Application started.
Common Formatting Fields
| Field | Information |
|---|---|
%(asctime)s
|
Time when the log record was created. |
%(levelname)s
|
Severity level of the record. |
%(name)s
|
Name of the logger. |
%(module)s
|
Module that created the record. |
%(funcName)s
|
Function that created the record. |
%(lineno)d
|
Source-code line number. |
%(message)s
|
Final formatted log message. |
Include Variables in Log Messages
import logging
logging.basicConfig(
level=logging.INFO,
format=(
"%(levelname)s | "
"%(message)s"
)
)
customer_id = "CUST-101"
order_total = 2500
logging.info(
"Order processed for customer %s with total %s",
customer_id,
order_total
)
Possible output:
INFO | Order processed for customer CUST-101 with total 2500
Create a Named Logger
Application modules commonly create a logger using the module name.
import logging
logger = logging.getLogger(
__name__
)
logger.warning(
"A named logger created this message."
)
The __name__ value identifies the module that created
the logger.
Use Logging Inside a Function
import logging
logging.basicConfig(
level=logging.INFO,
format=(
"%(levelname)s | "
"%(name)s | "
"%(message)s"
)
)
logger = logging.getLogger(
__name__
)
def process_order(order_number):
logger.info(
"Processing order %s",
order_number
)
logger.info(
"Order %s processed successfully",
order_number
)
process_order(
"ORD-101"
)
Record Exception Information
Use logger.exception() inside an exception handler
when traceback information should be included.
import logging
logging.basicConfig(
level=logging.ERROR
)
logger = logging.getLogger(
__name__
)
try:
result = 100 / 0
except ZeroDivisionError:
logger.exception(
"The calculation failed."
)
The generated record includes the message and exception traceback.
Create a Console Handler
A handler determines where matching log records are sent.
import logging
logger = logging.getLogger(
"application"
)
logger.setLevel(
logging.DEBUG
)
console_handler = logging.StreamHandler()
console_handler.setLevel(
logging.INFO
)
formatter = logging.Formatter(
"%(levelname)s | %(name)s | %(message)s"
)
console_handler.setFormatter(
formatter
)
logger.addHandler(
console_handler
)
logger.debug(
"Diagnostic message"
)
logger.info(
"Application is ready"
)
Possible output:
INFO | application | Application is ready
Core Logging Components
| Component | Responsibility |
|---|---|
| Logger | Creates log records for an application or module. |
| Handler | Sends records to a destination. |
| Formatter | Defines the displayed structure of a log record. |
| Filter | Applies additional rules to record processing. |
| Log Record | Contains the information associated with one event. |
print() vs Logging
print()
- Useful for simple visible output
- Does not provide severity levels
- Requires manual formatting
- Difficult to control across large applications
Logging
- Provides severity levels
- Supports structured formatting
- Supports multiple output destinations
- Can be configured for application modules
Practical Example: Order Processing
import logging
logging.basicConfig(
level=logging.INFO,
format=(
"%(asctime)s | "
"%(levelname)s | "
"%(message)s"
)
)
logger = logging.getLogger(
__name__
)
def process_order(order):
order_number = order.get(
"order_number"
)
amount = order.get(
"amount",
0
)
logger.info(
"Processing order %s",
order_number
)
if amount <= 0:
logger.error(
"Order %s has an invalid amount",
order_number
)
return False
logger.info(
"Order %s processed successfully",
order_number
)
return True
order = {
"order_number": "ORD-101",
"amount": 2500
}
process_order(order)
Common Mistakes
Using the Wrong Log Level
Recording ordinary events as errors makes important failures harder to identify.
Configuring Logging Repeatedly
Repeated configuration can produce confusing or duplicate behavior.
Adding the Same Handler More Than Once
Multiple identical handlers can cause duplicate output.
Logging Sensitive Information
Logs may be stored, monitored, shared, or retained.
Logging Best Practices
Recommended Practices
- Use a named logger for application modules.
- Select a log level that matches the event.
- Include enough context to identify the affected operation.
- Use consistent formatting throughout the application.
- Record exceptions with traceback information when useful.
- Avoid recording passwords, tokens, secrets, or confidential business data.
- Do not use logging as the only mechanism for user-visible error communication.
- Follow organizational logging, retention, privacy, and security requirements.
Knowledge Check
Is logging part of the standard library?
Yes. It can be imported using
import logging.
Which level contains detailed diagnostics?
The DEBUG level is used for detailed diagnostic information.
How do you create a module logger?
logger = logging.getLogger(
__name__
)
How do you record an exception traceback?
try:
perform_operation()
except Exception:
logger.exception(
"The operation failed."
)
Logging Quick Reference
import logging
# Configure basic logging
logging.basicConfig(
level=logging.INFO,
format=(
"%(asctime)s | "
"%(levelname)s | "
"%(name)s | "
"%(message)s"
)
)
# Create a module logger
logger = logging.getLogger(
__name__
)
# Record messages
logger.debug(
"Diagnostic details"
)
logger.info(
"Operation completed"
)
logger.warning(
"Unexpected condition"
)
logger.error(
"Operation failed"
)
logger.critical(
"Application cannot continue"
)
Summary
What You Learned
- Python provides logging through its standard library.
- Log levels classify records according to severity.
-
basicConfig()provides introductory configuration. - Formatters control the structure of displayed records.
- Named loggers identify application modules.
- Handlers determine where log records are sent.
-
logger.exception()records exception information. - Sensitive information should not be written to logs.
Key Takeaway
Use Python's logging module to record application events with appropriate severity levels, consistent context, and controlled formatting. Create named loggers for modules and never place secrets or unnecessary sensitive information in log messages.