python笔记2 - logging模块
Python 的 logging 模块是一个功能强大的日志记录工具,可以替代简单的 print(),支持不同级别、输出到文件/控制台、自动格式化等。下面从基础到进阶介绍常用用法。
1 基本配置
import logging
# 基本配置: 级别, 格式, 输出位置
# basicConfig() 必须在任何日志记录前调用一次,且只能生效一次。
logging.basicConfig(
level = logging.INFO, # 记录INFO及其以上级别
format='%(asctime)s - %(name)s %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(),
logging.FileHandler('my.log')
]
)
# 使用不同级别记录日志
logging.debug('这是调试信息, 默认不显示')
logging.info('这是程序启动信息')
logging.warning('这是警告信息: CPU负载高')
logging.error('这是错误信息: 程序启动失败')
logging.critical('这是非常重要的信息')
运行后, 在执行这个脚本的目录中产生一个my.log的文件, 控制台和这个文件中都会产生以下信息:
2026-04-14 15:35:22,555 - root INFO - 这是程序启动信息
2026-04-14 15:35:22,557 - root WARNING - 这是警告信息: CPU负载高
2026-04-14 15:35:22,557 - root ERROR - 这是错误信息: 程序启动失败
2026-04-14 15:35:22,557 - root CRITICAL - 这是非常重要的信息
2. 日志级别
| 级别 | 数值 | 用途 |
|---|---|---|
DEBUG |
10 | 详细的调试信息 |
INFO |
20 | 正常操作信息 |
WARNING |
30 | 潜在问题警告(默认级别) |
ERROR |
40 | 错误,部分功能失效 |
CRITICAL |
50 | 严重错误,程序可能中止 |
设置 level=logging.DEBUG 后,所有级别都会被记录。
3. 记录变量信息
beamline = "XPS"
devices = 25
logging.info(f"station {beamline} devices {devices}") # f-string 方式(推荐)
logging.info("station name: %s devices: %d" % (beamline, devices)) # 旧式格式化(延迟计算,性能更好)
运行后:
2026-04-14 15:43:35,148 - root INFO - station XPS devices 25
2026-04-14 15:43:35,148 - root INFO - station name: XPS devices: 25
4. 更灵活的结构:Logger、Handler、Formatter
basicConfig() 适用于简单场景。复杂需求(不同模块不同级别、多个输出目标、不同格式)需手动配置。
import logging
# 1. 创建 Logger, 设置日志级别
logger = logging.getLogger('__name__')
logger.setLevel(logging.DEBUG)
# 2. 创建 Handler(控制台)
console_handler = logging.StreamHandler()
# 控制台只显示 WARNING 及以上
console_handler.setLevel(logging.WARNING)
# 3. 创建 Handler(文件)
file_handler = logging.FileHandler('all.log')
# 文件记录所有级别
file_handler.setLevel(logging.DEBUG)
# 4. 定义格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
# 5. 添加 Handler 到 Logger
logger.addHandler(console_handler)
logger.addHandler(file_handler)
# 使用
logger.debug('调试信息只写入文件,不显示控制台')
logger.warning('警告信息, 同时写入文件和显示控制台')
5. 常用格式化字段
| 字段 | 含义 |
|---|---|
%(asctime)s |
时间(可配置 datefmt) |
%(name)s |
Logger 名称 |
%(levelname)s |
日志级别文本 |
%(message)s |
日志消息 |
%(filename)s |
文件名 |
%(lineno)d |
行号 |
%(funcName)s |
函数名 |
%(process)d |
进程ID |
%(thread)d |
线程ID |
6.在多个模块中使用
主模块:
import logging
import submodule
logging.basicConfig(level=logging.INFO, format='%(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
logger.info('主程序启动')
submodule.do_something()
被调用模块submodule.py:
import logging
# 名称自动为 'submodule'
logger = logging.getLogger(__name__)
def do_something():
logger.info('模块内信息')
调用结果为:
__main__ - INFO - 主程序启动
submodule - INFO - 模块内信息
7. 配置文件方式(推荐用于生产)
使用 fileConfig 或 dictConfig 可以分离配置与代码。
配置文件:
[loggers]
keys=root,myapp
[handlers]
keys=consoleHandler,fileHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=WARNING
handlers=consoleHandler
[logger_myapp]
level=DEBUG
handlers=consoleHandler,fileHandler
qualname=myapp
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[handler_fileHandler]
class=FileHandler
level=DEBUG
formatter=simpleFormatter
args=('app.log', 'a')
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
整体结构
配置文件分为多个节(section):
- [loggers]:声明有哪些 logger 实例。
- [handlers]:声明有哪些 handler 实例。
- [formatters]:声明有哪些 formatter 实例。
然后分别定义每个 logger、handler、formatter 的具体属性。
1. [loggers] 节
作用:列出配置文件中定义的所有 logger 名称。
[loggers]
keys=root,myapp
- keys:逗号分隔的 logger 标识符。这里有两个 logger:
- root:根 logger,是日志系统的顶层,所有未指定父级的 logger 默认继承它。
myapp:自定义的 logger,名为 myapp。
注意:keys 中的名称只是引用,真正的 logger 名称由后面的 [logger_xxx] 节中的 qualname 指定(对于 root 例外,它固定为根)。
2. [handlers]节
作用:列出所有 handler 的名称。
[handlers]
keys=consoleHandler,fileHandler
keys:这里定义了两种处理器:
- consoleHandler:输出到控制台(标准输出)。
- fileHandler:输出到文件。
3. [formatters]节
作用:列出所有 formatter 的名称。
[formatters]
keys=simpleFormatter
keys:这里只有一个格式化器 simpleFormatter,用于定义日志消息的输出格式。
4 . [logger_root]节
[logger_root]
level=WARNING
handlers=consoleHandler
作用:配置根 logger。
- level:根 logger 的日志级别为 WARNING。这意味着只有级别 ≥ WARNING 的日志(WARNING、ERROR、CRITICAL)才会被处理,更低级别(DEBUG、INFO)会被忽略。
- handlers:根 logger 关联的 handler 列表(此处只有 consoleHandler)。所有传递给根 logger 的日志消息都会交给这些 handler 处理。
注意:根 logger 没有 qualname 和 propagate 属性,因为它就是日志树的根,不存在父级。
5. [logger_myapp]节
[logger_myapp]
level=DEBUG
handlers=consoleHandler,fileHandler
qualname=myapp
propagate=0
作用:配置名为 myapp 的自定义 logger。
- level:该 logger 的日志级别为 DEBUG,会接收所有 DEBUG 及以上级别的日志。
- handlers:该 logger 关联两个 handler:consoleHandler 和 fileHandler。日志消息会同时输出到控制台和文件。
- qualname:真正的 logger 名称。程序中使用 logging.getLogger('myapp') 获取的就是这个 logger。qualname 可以包含点号表示层级(如 myapp.sub),但这里只是简单字符串。
- propagate:是否将日志消息传播给父级 logger。
- propagate=0(或 False)表示禁止传播。即 myapp 的日志消息不会传递给根 logger 或其他父级 logger。
- 如果 propagate=1(默认),则除了自己关联的 handler 外,消息还会向上传递给父级(最终到根)的 handler,可能导致重复输出。
因为这里 propagate=0,所以 myapp 的日志只会由它自己的两个 handler 处理,根 logger 的 consoleHandler 不会收到这些日志(即使它们同名也不会重复)
6. [handler_consoleHandler]节
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
作用:配置名为 consoleHandler 的处理器。
- class:处理器的类名。StreamHandler 表示输出到流(如控制台)。Python 会从 logging 模块中导入这个类。
- level:该 handler 自身的日志级别过滤器。只有级别 ≥ DEBUG 的日志才会被这个 handler 处理。这里设为 DEBUG,意味着所有级别的日志都能通过。
- formatter:指定使用哪个格式化器。这里使用 simpleFormatter(定义在后面)。
- args:传递给 handler 类的构造参数。StreamHandler 的构造函数接受一个流对象,sys.stdout 表示标准输出(控制台)。args=(sys.stdout,) 是一个元组,对应 __init__(self, stream=None) 的参数。
注意:虽然 myapp logger 的级别是 DEBUG,但 handler 的级别也是 DEBUG,所以两者一致。如果 handler 级别设为 INFO,则即使 logger 收到 DEBUG 日志,handler 也会丢弃它。
7. [handler_fileHandler]节
作用:配置名为 fileHandler 的处理器。
[handler_fileHandler]
class=FileHandler
level=DEBUG
formatter=simpleFormatter
args=('app.log', 'a')
- class:FileHandler 表示输出到文件。
- level:同样为 DEBUG,接收所有级别日志。
- formatter:使用相同的 simpleFormatter。
- args:FileHandler 构造参数:
- 'app.log':文件名。
- 'a':文件打开模式,'a' 表示追加(append)。如果文件已存在,新日志追加到末尾;如果不存在则创建。
作用:定义日志消息的格式。
8. [formatter_simpleFormatter]节
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
format:字符串模板,包含变量(由 LogRecord 属性填充):
- %(asctime)s:日志产生的时间(默认格式为 YYYY-MM-DD HH:MM:SS,mmm,可单独设置 datefmt 修改)。
- %(name)s:logger 的名称(例如 'myapp' 或 'root')。
- %(levelname)s:日志级别文本(如 DEBUG, INFO)。
- %(message)s:实际的日志消息内容。
配置生效
在python程序中,像如下加载配置文件:
import logging
from logging import config
import os
dir_name = os.path.dirname(os.path.abspath(__file__))
config_file_path = os.path.join(dir_name, 'logging.conf')
print(f"config file path:{config_file_path}")
config.fileConfig(config_file_path)
logger = logging.getLogger('myapp') # 获取名为 myapp 的 logger
logger.debug('调试信息') # 会输出到控制台和 app.log
运行结果, 在控制台和app.log文件中都会有以下信息:
2026-04-14 21:55:41,584 - myapp - DEBUG - 调试信息
总结:整个配置的工作流程
1. 程序启动时加载配置文件,创建 root 和 myapp 两个 logger 实例。
2. 创建两个 handler:consoleHandler(输出到 sys.stdout)和 fileHandler(追加到 app.log)。
3. 创建格式化器 simpleFormatter,并附加到两个 handler 上。
4. 根 logger 的级别为 WARNING,关联 consoleHandler。
5. myapp logger 的级别为 DEBUG,关联两个 handler,并且禁止向上传播(propagate=0)。
6. 当代码中通过 logging.getLogger('myapp') 获取 logger 并记录日志时:
- 日志消息被 myapp logger 接收。
- 因为 level=DEBUG,所以所有级别日志都通过。
- 日志消息交给 consoleHandler 和 fileHandler,两个 handler 的级别也是 DEBUG,都会处理。
- 每个 handler 使用 simpleFormatter 格式化消息,然后分别输出到控制台和文件。
- 由于 propagate=0,消息不会发送给根 logger,因此根 logger 的 consoleHandler 不会再次输出(避免重复)。
如果某个日志级别低于 DEBUG(如 NOTSET),则不会被任何地方处理。
更多推荐



所有评论(0)