一、为什么需要日志?
在开发 Python 应用时,我们经常需要追踪程序的运行状态、调试错误、记录关键操作信息。虽然print()能应付简单的调试场景,但在正式项目中,日志系统才是更专业的选择。Python 内置的logging模块提供了灵活、可配置的日志记录功能,支持多个输出目标、自定义格式和分级管理,是每个 Python 开发者的必备技能。
二、核心概念速览
1. 日志级别(Level)
日志级别决定了信息的重要程度。logging 模块定义了以下标准级别,数值越大优先级越高:
- DEBUG(10):调试信息,用于开发阶段排查问题。
- INFO(20):普通信息,记录程序正常运行的关键步骤。
- WARNING / WARN(30):警告信息,表示可能出现问题但程序仍可继续运行。
- ERROR(40):错误信息,表示发生了影响功能的错误。
- CRITICAL / FATAL(50):严重错误,表示程序可能无法继续运行。
通过设置日志级别,你可以灵活控制输出哪些信息:比如开发时设为 DEBUG 查看所有细节,部署到生产环境时升到 WARNING 只关注警告和错误。
2. 日志格式(Format)
日志格式决定了每条日志的输出内容。常用的格式化字段包括:
| 格式字段 | 含义 |
|---|---|
%(asctime)s | 日志时间戳,格式可自定义 |
%(name)s | 日志实例名,默认为 root |
%(levelname)s | 日志级别英文名(如 DEBUG、INFO) |
%(levelno)s | 日志级别数值(10、20、30 等) |
%(message)s | 日志内容 |
%(lineno)d | 输出日志的代码行号 |
%(module)s | 调用日志的模块名 |
%(filename)s | 文件名(不含路径) |
%(pathname)s | 文件完整路径 |
3. 处理器(Handlers)
处理器决定日志的输出目的地。最常用的两种是:
- StreamHandler:流式处理器,输出到控制台(
sys.stdout或sys.stderr)。 - FileHandler:文件处理器,将日志写入指定文件。
通过组合多个处理器,你可以实现“控制台实时查看 + 文件持久化存储”的日志方案,并且每个处理器都可以独立设置日志级别和格式。
三、基础用法:快速上手
使用logging.basicConfig()可以快速配置全局日志系统。以下示例同时启用了控制台和文件输出:
import logging import sys logging.basicConfig( level=logging.DEBUG, format='%(lineno)d --%(module)s--%(filename)s--%(name)s--%(levelname)s --%(message)s', handlers=[ logging.StreamHandler(sys.stdout), # 输出到控制台 logging.FileHandler("log") # 输出到文件 ] ) logging.debug("debug666") logging.info("info666") logging.warning("warning666") logging.error("error666") logging.critical("critical666")这种方式适合小型脚本或测试场景,但无法对不同处理器单独设置级别和格式。更灵活的方案是单独配置每个处理器。
四、进阶用法:多实例与独立处理器
在实际项目中,我们通常需要为不同模块创建独立的日志实例,并为每个实例配置各自的处理器和格式。下面是一个完整示例:
import logging ----- 创建第一个日志实例 ----- logger = logging.getLogger(name) logger.setLevel(logging.DEBUG) # 实例级别设为 DEBUG,允许所有级别通过 控制台处理器:只输出 INFO 及以上级别 stream_handler = logging.StreamHandler() stream_handler.setLevel(logging.INFO) stream_formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) stream_handler.setFormatter(stream_formatter) logger.addHandler(stream_handler) 文件处理器:只输出 WARNING 及以上级别 file_handler = logging.FileHandler('log.txt') file_handler.setLevel(logging.WARNING) file_formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) file_handler.setFormatter(file_formatter) logger.addHandler(file_handler) 测试输出 logger.debug("debug") logger.info("info") logger.warning("warn") logger.error("error") logger.critical("fatal") ----- 创建第二个日志实例(独立配置)----- logger2 = logging.getLogger("用户模块") logger2.setLevel(logging.DEBUG) file_handler2 = logging.FileHandler('log2.txt', encoding='utf-8') file_handler2.setLevel(logging.WARNING) file_formatter2 = logging.Formatter( '%(asctime)s - %(levelname)s - %(name)s - %(message)s' ) file_handler2.setFormatter(file_formatter2) logger2.addHandler(file_handler2) logger2.debug("debug") logger2.info("info") logger2.warning("warn") logger2.error("error") logger2.critical("fatal")代码解析
- 实例创建:
getLogger(__name__)以当前模块名创建日志实例;getLogger("用户模块")创建自定义名称的实例,便于按模块区分日志来源。 - 级别的两层过滤:日志实例和处理器各自有级别设置。只有当日志消息的级别同时满足“大于等于实例级别”和“大于等于处理器级别”时,才会被输出。
- 独立配置:每个日志实例拥有独立的处理器集合,互不干扰。第一个实例的 DEBUG 日志不会出现在控制台(被流处理器过滤),第二个实例的日志也不会写入
log.txt。
五、运行结果解读
运行上述代码后,控制台将看到:
2026-07-30 12:00:00,123 - __main__ - INFO - info 2026-07-30 12:00:00,124 - __main__ - WARNING - warn 2026-07-30 12:00:00,124 - __main__ - ERROR - error 2026-07-30 12:00:00,125 - __main__ - CRITICAL - fatal注意:debug消息没有出现在控制台,因为流处理器的级别设为了 INFO。
文件log.txt中只有 WARNING 及更高级别的日志(warn、error、fatal),DEBUG 和 INFO 被文件处理器过滤掉了。
文件log2.txt中只包含第二个实例的 WARNING 及以上级别日志,两个日志实例完全独立。
六、总结
Python 的logging模块提供了从简单到复杂的日志解决方案:
- 快速开始:用
basicConfig()一行搞定基础配置。 - 精细控制:为每个处理器独立设置级别和格式,实现“控制台看详情 + 文件存要害”的分级记录。
- 模块化隔离:用
getLogger()创建不同命名的实例,让各模块的日志互不干扰。
掌握这些基础后,你还可以进一步探索日志的轮转(RotatingFileHandler)、过滤器(Filter)和配置文件(logging.config)等高级特性,构建健壮的应用日志体系。