本文目录导读:

在Python中实现日志打印,推荐使用内置的logging模块,它比简单的print更强大、更灵活。
以下是几种常见的实现案例,从基础到高级:
最基础的配置(快速上手)
适合小型脚本、快速调试。
import logging
# 基础配置:设置日志级别和格式
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s')
# 使用不同级别的日志
logging.debug("这是调试信息(不会打印,因为级别是INFO)")
logging.info("程序开始运行")
logging.warning("这是一个警告")
logging.error("发生了一个错误")
logging.critical("严重错误,程序可能崩溃")
输出:
2025-03-30 10:30:00,123 - INFO - 程序开始运行
2025-03-30 10:30:00,124 - WARNING - 这是一个警告
2025-03-30 10:30:00,125 - ERROR - 发生了一个错误
2025-03-30 10:30:00,126 - CRITICAL - 严重错误,程序可能崩溃
配置日志格式(时间、文件名、行号)
适合需要定位代码位置的场景。
import logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s [%(levelname)s] %(filename)s:%(lineno)d - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
def divide(a, b):
logging.info(f"正在计算 {a} / {b}")
try:
result = a / b
logging.debug(f"计算结果: {result}")
return result
except ZeroDivisionError:
logging.error("除数不能为0", exc_info=True)
return None
divide(10, 2)
divide(10, 0)
输出(示例):
2025-03-30 10:30:00 [INFO] demo.py:9 - 正在计算 10 / 2
2025-03-30 10:30:00 [DEBUG] demo.py:11 - 计算结果: 5.0
2025-03-30 10:30:00 [INFO] demo.py:9 - 正在计算 10 / 0
2025-03-30 10:30:00 [ERROR] demo.py:14 - 除数不能为0
Traceback (most recent call last):
File "demo.py", line 10, in divide
result = a / b
ZeroDivisionError: division by zero
同时输出到控制台和文件
适合需要持久化日志的生产环境。
import logging
# 创建 logger
logger = logging.getLogger('my_app')
logger.setLevel(logging.DEBUG)
# 1. 文件处理器(写入文件)
file_handler = logging.FileHandler('app.log', encoding='utf-8')
file_handler.setLevel(logging.DEBUG)
# 2. 控制台处理器(打印到屏幕)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 配置格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
# 添加处理器到 logger
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 使用 logger
logger.debug("调试信息 -> 仅写入文件")
logger.info("普通信息 -> 文件 + 控制台")
logger.warning("警告信息")
使用配置文件(生产环境推荐)
配置文件 logging_config.json
{
"version": 1,
"disable_existing_loggers": false,
"formatters": {
"standard": {
"format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
},
"detailed": {
"format": "%(asctime)s [%(levelname)s] %(filename)s:%(lineno)d - %(message)s"
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "INFO",
"formatter": "standard",
"stream": "ext://sys.stdout"
},
"file": {
"class": "logging.FileHandler",
"level": "DEBUG",
"formatter": "detailed",
"filename": "app.log",
"encoding": "utf-8"
}
},
"loggers": {
"": {
"handlers": ["console", "file"],
"level": "DEBUG",
"propagate": true
},
"my_module": {
"handlers": ["console"],
"level": "WARNING",
"propagate": false
}
}
}
Python 代码
import logging.config
import json
# 加载配置
with open('logging_config.json', 'r', encoding='utf-8') as f:
config = json.load(f)
logging.config.dictConfig(config)
logger = logging.getLogger(__name__)
logger.info("应用启动成功")
logger.debug("这是一条调试信息")
日志轮转(防止日志文件过大)
import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger('rotating_logger')
logger.setLevel(logging.INFO)
# 每个文件最大 1MB,保留最近 3 个备份
handler = RotatingFileHandler(
'app.log',
maxBytes=1_000_000, # 1MB
backupCount=3,
encoding='utf-8'
)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
# 模拟大量日志
for i in range(10000):
logger.info(f"日志第 {i} 条")
装饰器方式自动记录函数日志
import logging
from functools import wraps
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
logger = logging.getLogger(__name__)
def log_function_call(func):
@wraps(func)
def wrapper(*args, **kwargs):
logger.info(f"调用 {func.__name__}(args={args}, kwargs={kwargs})")
try:
result = func(*args, **kwargs)
logger.info(f"{func.__name__} 返回: {result}")
return result
except Exception as e:
logger.error(f"{func.__name__} 异常: {e}", exc_info=True)
raise
return wrapper
@log_function_call
def calculate(x, y):
return x / y
calculate(10, 2)
# 2025-03-30 10:30:00 - 调用 calculate(args=(10, 2), kwargs={})
# 2025-03-30 10:30:00 - calculate 返回: 5.0
日志级别说明
| 级别 | 数值 | 使用场景 |
|---|---|---|
| DEBUG | 10 | 调试信息,开发时使用 |
| INFO | 20 | 正常运行信息 |
| WARNING | 30 | 有潜在问题但程序仍可运行 |
| ERROR | 40 | 发生了错误,部分功能受影响 |
| CRITICAL | 50 | 严重错误,程序可能无法继续运行 |
总结建议
- 开发调试:
basicConfig(level=DEBUG)简单配置 - 生产环境:同时输出到控制台(INFO)和文件(DEBUG)
- 大型项目:使用配置文件统一管理
- 重要操作:使用装饰器统一记录函数日志
- 日志过大:使用
RotatingFileHandler进行轮转
推荐在项目早期就引入 logging 模块,避免后期大量替换 print。