1. 基本概念
日志层级(Level)枚举值:DEBUG, INFO, WARNING, ERROR, CRITICAL
常用 Handler 类枚举:StreamHandler, FileHandler, RotatingFileHandler, TimedRotatingFileHandler
| |
|---|
| Logger | 负责产生日志记录的对象,通常通过 logging.getLogger(name) 获取。日志层级(level)决定哪些记录会被处理。 |
| Handler | 将日志输出到不同目标(控制台、文件、网络、SMTP 等)。每个 Handler 也有自己的 level。 |
| Formatter | 定义日志记录的文本格式,常用的占位符有 %(asctime)s、%(levelname)s、%(name)s、%(message)s 等。 |
| Filter | 用来进一步筛选日志记录,能够基于 logger 名称、level 或自定义条件过滤。 |
日志层级(Level)(从低到高):DEBUG、INFO、WARNING、ERROR、CRITICAL。
1.1 示例 – “Hello World”
import logging
# 只需要一行代码即可完成基本配置,默认输出到控制台,level 为 INFO
logging.basicConfig(level=logging.INFO)
logging.debug('这条不会显示,因为默认 level 为 INFO')
logging.info('程序启动')
logging.warning('这是一条警告')
logging.error('出现错误')
logging.critical('严重错误')
运行后会在终端看到 INFO 以上级别的日志。`
2. 完整的配置方式
2.1 logging.basicConfig
basicConfig 适合一次性配置,常用参数如下:
| | |
|---|
level | logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL | |
format | 任意符合 logging.Formatter 语法的字符串,例如 '%(asctime)s %(levelname)s %(message)s' | |
datefmt | 任意 strftime 格式字符串,例如 '%Y-%m-%d %H:%M:%S' | |
filename | | |
filemode | 'a' | |
handlers | list,元素为 logging.Handler 实例,如 logging.StreamHandler()、logging.FileHandler('app.log') 等 | 自定义 Handler 列表,覆盖 filename/stream |
示例:日志同时写文件和控制台
import logging
log_format = '%(asctime)s | %(levelname)-8s | %(name)s | %(message)s'
logging.basicConfig(
level=logging.DEBUG,
format=log_format,
datefmt='%Y-%m-%d %H:%M:%S',
handlers=[
logging.FileHandler('app.log', encoding='utf-8'),
logging.StreamHandler()
]
)
logger = logging.getLogger('myapp')
logger.debug('调试信息')
logger.info('业务启动')
2.2 使用字典(dictConfig)
对于较复杂的需求,推荐 logging.config.dictConfig。它能够一次性声明多个 logger、handler、formatter。
完整示例(控制台 + rotating file + 邮件)
import logging
import logging.config
CONFIG = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '%(asctime)s | %(levelname)s | %(name)s | %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S'
},
'simple': {
'format': '%(levelname)s: %(message)s'
}
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'level': 'INFO',
'formatter': 'simple',
'stream': 'ext://sys.stdout'
},
'file_rotating': {
'class': 'logging.handlers.RotatingFileHandler',
'level': 'DEBUG',
'formatter': 'standard',
'filename': 'myapp.log',
'maxBytes': 1024*1024, # 1 MiB
'backupCount': 3,
'encoding': 'utf-8'
}
},
'loggers': {
'myapp': {
'level': 'DEBUG',
'handlers': ['console', 'file_rotating', 'mail'],
'propagate': False
}
}
}
logging.config.dictConfig(CONFIG)
logger = logging.getLogger('myapp')
logger.debug('调试信息 – 会写入文件')
logger.info('普通信息 – 只显示在控制台')
logger.error('错误信息 – 控制台、文件')
只需把 CONFIG 写入 JSON/YAML 文件后,用 logging.config.fileConfig('logging.conf') 读取即可。
3. 常用 Handler 说明
| |
|---|
StreamHandler | |
FileHandler | |
RotatingFileHandler | |
TimedRotatingFileHandler | |
各 Handler 支持的常用配置参数(示例)
1. StreamHandler
| | |
|---|
stream | sys.stdout(默认),sys.stderr,任意类 file‑like 对象 | |
level | | |
formatter | | |
2. FileHandler
| | |
|---|
filename | | |
mode | 'a'(追加, 默认),'w'(覆盖),'x'(新建),'b'(二进制) | |
encoding | 'utf-8' | |
delay | True | |
level | | |
3. RotatingFileHandler
| | |
|---|
filename | | |
mode | | |
maxBytes | | |
backupCount | | |
encoding | | |
4. TimedRotatingFileHandler
| | |
|---|
filename | | |
when | 'S'(秒),'M'(分钟),'H'(小时),'D'(天),'midnight','W0'‑'W6'(周) | |
interval | | |
backupCount | | |
encoding、delay、utc、atTime、level、formatter | | |
示例:TimedRotatingFileHandler(每日切分)
import logging
from logging.handlers import TimedRotatingFileHandler
handler = TimedRotatingFileHandler(
'daily.log', when='midnight', interval=1, backupCount=7, encoding='utf-8'
)
handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
logger = logging.getLogger('daily')
logger.setLevel(logging.INFO)
logger.addHandler(handler)
logger.info('今天的日志')
4. 进阶技巧
4.1 为不同模块设定独立 logger
# module_a.py
import logging
log = logging.getLogger('myapp.module_a')
log.debug('module_a 调试')
# module_b.py
import logging
log = logging.getLogger('myapp.module_b')
log.info('module_b 正常运行')
在主配置中只需为 myapp 设置一次,子 logger 会自动继承(除非显式覆盖)
4.2 使用 extra 传递自定义字段
import logging
logger = logging.getLogger('extra_demo')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(user)s %(message)s')
handler = logging.StreamHandler()
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.info('登录成功', extra={'user': 'alice'}) # 2026-03-11 16:20:40,611 INFO alice 登录成功