
Python 的 logging 模块不是“用起来就行”的简单工具,而是需要按需设计的日志系统——核心在于分级控制、多目标输出、格式统一、上下文可追溯。直接调用 print() 或裸用 logging.debug() 很快会陷入日志混乱、关键信息丢失、线上无法排查的困境。
明确日志级别与使用场景
日志级别不是摆设,它决定了什么该记、什么该忽略。默认有 5 级(从低到高):DEBUG、INFO、WARNING、ERROR、CRITICAL。实际使用中要严格区分语义:
-
DEBUG:仅开发/调试时开启,如变量值、函数入参、SQL 参数;生产环境通常关闭 -
INFO:记录正常流程关键节点,如“用户登录成功”“订单创建完成”,用于确认服务运转正常 -
WARNING:非错误但需关注的情况,如配置项缺失回退默认值、接口响应超时但未失败 -
ERROR:发生异常但已捕获并处理,如数据库连接失败后启用备用源 -
CRITICAL:必须立即人工介入,如核心配置加载失败导致服务无法启动
配置 Handler 实现分发与持久化
一个 Logger 可绑定多个 Handler,实现“一份日志,多路输出”。常见组合:
-
StreamHandler:输出到终端(适合开发调试),默认输出到sys.stderr -
FileHandler:写入单个文件,适合小项目或临时记录 -
RotatingFileHandler:按大小轮转(如单个日志不超过 10MB,最多保留 5 个备份) -
TimedRotatingFileHandler:按时间轮转(如每天一个文件app.log.2024-06-15) -
SMTPHandler:ERROR+ 级别自动发邮件告警(需配置 SMTP 服务)
注意:不同 Handler 可设置不同 level,例如终端只显示 INFO+,而文件记录 DEBUG+,互不干扰。
立即学习“Python免费学习笔记(深入)”;
用 Formatter 统一日志结构
没有格式化的日志等于无意义字符串。推荐包含:时间、级别、模块名、行号、消息内容。例如:
2024-06-15 14:22:08,123 | INFO | auth.py:47 | User 'alice' logged in successfully实现方式:
formatter = logging.Formatter(
'%(asctime)s | %(levelname)-8s | %(name)s:%(lineno)d | %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)其中 %(name)s 是 Logger 名(建议用 __name__),便于定位来源模块;%(lineno)d 显示代码行号,排查极快。
构建可复用的 Logger 工厂
避免在每个文件里重复配置。推荐封装一个初始化函数,支持环境感知:
def setup_logger(name=__name__, level=logging.INFO, log_file=None):
logger = logging.getLogger(name)
logger.setLevel(level)
<pre class="brush:php;toolbar:false;"># 防止重复添加 handler(尤其被多次 import 时)
if not logger.handlers:
# 控制台输出
console = logging.StreamHandler()
console.setFormatter(formatter)
logger.addHandler(console)
# 文件输出(可选)
if log_file:
file_handler = RotatingFileHandler(
log_file, maxBytes=10*1024*1024, backupCount=5
)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger
在模块中直接使用:
logger = setup_logger(__name__, log_file='app.log')
logger.info("Service started")
这样既保证模块级命名隔离,又避免全局污染和重复 handler。










