logging 模块是 Python 的标准库,功能非常强大,相比于简单的 print() 语句,它提供了更灵活、更结构化的日志记录方式。
最简单的开始:直接使用 logging.debug()
如果你只是想快速开始,可以直接调用 logging 模块的各个级别函数。
import logging
# 默认情况下,logging 只显示 WARNING 级别及以上的日志
logging.debug("这是一条调试信息,你通常看不到它。")
logging.info("这是一条普通信息。")
logging.warning("这是一条警告信息!") # 你会看到这条
logging.error("这是一条错误信息!") # 你会看到这条
logging.critical("这是一条严重错误信息!") # 你会看到这条
运行结果:
你会只看到 WARNING、ERROR 和 CRITICAL 级别的日志。
WARNING:root:这是一条警告信息!
ERROR:root:这是一条错误信息!
CRITICAL:root:这是一条严重错误信息!
解释:
- 级别 (Level): 日志分为五个级别:
DEBUG,INFO,WARNING,ERROR,CRITICAL,级别越高,信息越重要。 - 默认行为: 默认的日志级别是
WARNING,并且日志格式是级别:logger名称:消息,输出目标是sys.stderr(标准错误流,通常也是你的控制台)。
核心概念:Logger, Handler, Formatter
要更好地控制日志输出,你需要理解 logging 的三个核心组件:
- Logger (记录器): 这是你的应用程序直接交互的对象,你通过
logger.debug()等方法来发送日志消息,每个 Logger 都有一个日志级别。 - Handler (处理器): 它的作用是“处理” Logger 发出的日志消息,并将其发送到指定的目的地(控制台、文件、网络等),一个 Logger 可以附加多个 Handler。
- Formatter (格式化器): 它定义了日志消息的最终输出格式,你可以自定义日志中包含哪些信息,如时间戳、级别、模块名、行号、消息等。
工作流程:
Logger 产生日志 -> 传递给 Handler -> Handler 使用 Formatter 格式化日志 -> 输出到目标(如控制台)。
完整的配置:如何自定义控制台日志
下面是一个完整的、推荐的配置示例,它展示了如何自定义日志级别、格式和输出目标。
import logging
# 1. 创建一个 Logger 实例
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG) # 设置 Logger 的日志级别为 DEBUG,这样它就不会过滤任何级别的日志
# 2. 创建一个 Handler,用于将日志输出到控制台
# StreamHandler 默认输出到 sys.stderr,你也可以指定为 sys.stdout
console_handler = logging.StreamHandler()
# 3. 设置 Handler 的日志级别
# 即使 Logger 设置为 DEBUG,Handler 也可以有自己的级别,实现更精细的控制
console_handler.setLevel(logging.INFO) # 只让 INFO 级别及以上的日志显示在控制台
# 4. 创建一个 Formatter,定义日志的格式
# %(asctime)s: 时间戳
# %(name)s: Logger 的名称 (通常是 __name__)
# %(levelname)s: 日志级别 (DEBUG, INFO, etc.)
# %(message)s: 日志消息
# %(filename)s: 模块名
# %(lineno)d: 行号
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s')
# 5. 将 Formatter 添加到 Handler
console_handler.setFormatter(formatter)
# 6. 将 Handler 添加到 Logger
logger.addHandler(console_handler)
# --- 现在开始使用 logger ---
logger.debug("这是一个调试信息,但被 Handler 过滤了,不会显示。")
logger.info("这是一条普通信息,会显示在控制台。")
logger.warning("这是一条警告信息,会显示在控制台。")
logger.error("这是一条错误信息,会显示在控制台。")
运行结果:
你会看到格式化后的、INFO 级别及以上的日志。
2025-10-27 10:30:00,123 - __main__ - INFO - your_script_name.py:34 - 这是一条普通信息,会显示在控制台。
2025-10-27 10:30:00,123 - __main__ - WARNING - your_script_name.py:35 - 这是一条警告信息,会显示在控制台。
2025-10-27 10:30:00,123 - __main__ - ERROR - your_script_name.py:36 - 这是一条错误信息,会显示在控制台。
推荐的最佳实践:使用 logging.config.dictConfig
对于复杂的应用程序,硬编码配置不是一个好习惯,推荐使用字典来配置 logging,这样可以更灵活地管理配置,甚至可以从配置文件(如 JSON 或 YAML)中加载。
import logging
import logging.config
# 定义配置字典
LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': False, # 不要禁用已经存在的 logger
'formatters': {
'standard': {
'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler', # 使用 StreamHandler 输出到控制台
'level': 'INFO', # 只处理 INFO 级别及以上
'formatter': 'standard', # 使用名为 'standard' 的格式化器
'stream': 'ext://sys.stdout', # 输出到标准输出 (也可以是 sys.stderr)
},
},
'loggers': {
'my_app_logger': { # 定义一个名为 'my_app_logger' 的 logger
'level': 'DEBUG', # 它自己记录所有级别
'handlers': ['console'], # 它只使用 'console' 这个 handler
'propagate': False, # 不要将日志传递给父 logger (如 root logger)
},
},
}
# 应用配置
logging.config.dictConfig(LOGGING_CONFIG)
# 获取我们定义的 logger
logger = logging.getLogger('my_app_logger')
# --- 使用 logger ---
logger.debug("这是一个调试信息,不会显示,因为 handler 的级别是 INFO。")
logger.info("应用启动成功。")
logger.warning("检测到一个潜在问题。")
优点:
- 集中管理: 所有日志配置都在一个地方,易于修改和维护。
- 可扩展: 可以轻松添加新的 Handler(比如一个文件
FileHandler)或 Formatter。 - 可配置化: 可以从外部文件加载配置,而无需修改代码。
不同场景下的建议
-
小型脚本或快速原型: 直接使用
logging.basicConfig()是最快的方式。import logging logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') logging.info("脚本开始运行...") -
中等规模的应用程序: 使用 第 3 节 中的方法(手动创建
Logger,Handler,Formatter),这是最常见和最灵活的方式,能让你清晰地看到日志的配置过程。 -
大型或复杂的应用程序: 强烈推荐使用 第 4 节 中的
logging.config.dictConfig方法,它将配置与代码分离,使得管理多个 logger 和 handler 变得非常简单。
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
直接调用 logging.info() |
简单,无需配置 | 无法自定义级别和格式,不灵活 | 快速测试、非常小的脚本 |
手动配置 (Logger, Handler) |
灵活,控制力强,易于理解 | 代码稍多 | 中等规模项目,需要精细控制日志时 |
basicConfig() |
一行代码搞定,快速 | 功能有限,通常只能配置一个根 logger | 小型脚本,临时调试 |
dictConfig() |
最佳实践,配置与代码分离,可扩展,强大 | 需要学习配置字典的结构 | 大型项目,复杂日志需求 |
希望这份详细的指南能帮助你完全掌握 Python 的 logging 模块在控制台上的使用!
