Pythonlogging不显示INFO日志解决方法
时间:2025-08-07 11:57:39 405浏览 收藏
一分耕耘,一分收获!既然都打开这篇《Python logging不显示INFO日志怎么办》,就坚持看下去,学下去吧!本文主要会给大家讲到等等知识点,如果大家对本文有好的建议或者看到有不足之处,非常欢迎大家积极提出!在后续文章我会继续更新文章相关的内容,希望对大家都有所帮助!
Python logging模块工作原理
Python的logging模块是一个强大而灵活的日志系统,它由几个核心组件构成:
- Logger(记录器): 这是应用程序中日志操作的入口点。每个Logger都有一个名称,并且可以形成一个层级结构。Logger负责接收日志消息,并决定是否将它们传递给处理器。
- Handler(处理器): Handler负责将Logger生成的日志消息发送到指定的目标,例如文件、控制台、网络套接字等。一个Logger可以有多个Handler。
- Formatter(格式器): Formatter定义了日志消息的输出格式,包括时间戳、日志级别、进程ID、消息内容等。
- Filter(过滤器): Filter提供了更细粒度的控制,可以在日志消息被Handler处理之前或之后进行过滤。
日志消息的生命周期大致如下:应用程序调用Logger的某个方法(如logger.info())生成一个日志记录(LogRecord)。该记录首先由Logger自身进行级别检查。如果通过,它将被传递给Logger附加的所有Handler,每个Handler再根据自己的级别设置决定是否处理该记录,并最终通过Formatter进行格式化输出。
日志级别过滤机制详解
在logging模块中,日志级别(如DEBUG, INFO, WARNING, ERROR, CRITICAL)是控制日志输出的关键。一个常见的误解是,只要将Handler的级别设置为INFO,所有INFO及更高级别的日志就会被输出。然而,日志记录的过滤实际上发生在两个主要阶段:
Logger级别的过滤: 当一个日志记录被创建时,它首先会与生成它的Logger实例的有效级别进行比较。如果日志记录的级别低于Logger的有效级别,那么该记录将被直接丢弃,不会传递给任何Handler。 关键点:新创建的Logger实例(通过logging.getLogger('name'))默认的级别是WARNING。这意味着,如果你不显式设置Logger的级别,那么DEBUG和INFO级别的日志消息将永远不会到达Handler,因为它们在Logger层面就被过滤掉了。
Handler级别的过滤: 如果日志记录通过了Logger的级别检查,它将被传递给Logger附加的所有Handler。每个Handler也会根据自己的级别设置对日志记录进行第二次检查。如果日志记录的级别低于Handler的级别,那么该Handler将不会处理这条记录。
因此,要确保INFO级别的日志能够被输出,你需要同时满足两个条件:
- Logger的级别必须设置为INFO或更低(例如DEBUG)。
- 目标Handler的级别也必须设置为INFO或更低。
问题分析与解决方案
原始代码中,setup_logger函数为FileHandler和StreamHandler都设置了相应的级别(例如info_log.setLevel(logging.INFO)),但却没有为Logger实例本身设置级别。由于新创建的Logger实例默认级别是WARNING,因此当logger.info('This is an info message')被调用时,INFO级别的消息在到达Logger时就被其默认的WARNING级别过滤掉了,无法传递给任何Handler,最终导致INFO日志未被打印。
解决方案:在setup_logger函数中,为logger实例显式设置一个合适的级别,例如logging.INFO或logging.DEBUG,以确保所有期望的低级别日志能够通过Logger的初步检查。
示例代码
以下是修正后的setup_logger函数和使用示例:
import logging import os # 确保日志目录存在 LOG_DIR = './logs' os.makedirs(LOG_DIR, exist_ok=True) def setup_logger(dtc_name, log_dir, is_debug=False, is_interactive=False): """ 配置并返回一个Logger实例。 :param dtc_name: Logger的名称。 :param log_dir: 日志文件存放的目录。 :param is_debug: 是否启用调试模式,影响控制台输出级别。 :param is_interactive: 是否启用交互模式,影响控制台输出级别。 :return: 配置好的Logger实例。 """ formatter = logging.Formatter("%(asctime)s %(process)s %(levelname)s - %(message)s") logger = logging.getLogger(dtc_name) # 关键修正:设置Logger自身的级别 # 根据需求,如果需要看到INFO或DEBUG日志,Logger级别必须设置得足够低 logger.setLevel(logging.DEBUG) # 设置Logger的最低处理级别为DEBUG,以确保所有消息都能通过 # 避免重复添加Handler,这在多次调用setup_logger时很有用 if logger.handlers: for handler in logger.handlers[:]: logger.removeHandler(handler) # INFO级别日志文件处理器 info_log_path = os.path.join(log_dir, f"{dtc_name}.log") info_log = logging.FileHandler(info_log_path) info_log.setFormatter(formatter) info_log.setLevel(logging.INFO) # 文件处理器只记录INFO及以上级别 logger.addHandler(info_log) # ERROR级别日志文件处理器 error_log_path = os.path.join(log_dir, f"{dtc_name}_error.log") error_log = logging.FileHandler(error_log_path) error_log.setFormatter(formatter) error_log.setLevel(logging.ERROR) # 错误文件处理器只记录ERROR及以上级别 logger.addHandler(error_log) # 控制台日志处理器 console_log = logging.StreamHandler() console_log.setFormatter(formatter) # 根据is_debug和is_interactive设置控制台输出级别 if is_debug: console_log.setLevel(logging.DEBUG) # 调试模式下控制台输出DEBUG及以上 elif is_interactive: console_log.setLevel(logging.INFO) # 交互模式下控制台输出INFO及以上 else: console_log.setLevel(logging.WARNING) # 默认情况下控制台输出WARNING及以上 logger.addHandler(console_log) return logger # 使用示例 def main(): # 设置logger,is_debug和is_interactive都为False,控制台默认输出WARNING及以上 # 但由于Logger本身级别设置为DEBUG,所有日志(DEBUG, INFO, WARNING, ERROR, CRITICAL) # 都会被Logger接收并传递给Handler logger = setup_logger('ExampleLogger', LOG_DIR, is_debug=False, is_interactive=False) print("--- 当前Logger和Handlers的级别 ---") print(f"Logger Level: {logging.getLevelName(logger.level)}") for handler in logger.handlers: print(f"Handler: {handler} | Level: {logging.getLevelName(handler.level)}") print("----------------------------------") # 记录不同级别的消息 logger.debug('This is a debug message') logger.info('This is an info message') logger.warning('This is a warning message') logger.error('This is an error message') logger.critical('This is a critical message') if __name__ == "__main__": main()
运行上述代码,你将看到如下输出(具体时间戳和进程ID会有所不同):
--- 当前Logger和Handlers的级别 --- Logger Level: DEBUG Handler:| Level: INFO Handler: | Level: ERROR Handler: (WARNING)> | Level: WARNING ---------------------------------- 2023-XX-XX XX:XX:XX,XXX XXX WARNING - This is a warning message 2023-XX-XX XX:XX:XX,XXX XXX ERROR - This is an error message 2023-XX-XX XX:XX:XX,XXX XXX CRITICAL - This is a critical message
在./logs/ExampleLogger.log文件中,你将看到:
2023-XX-XX XX:XX:XX,XXX XXX INFO - This is an info message 2023-XX-XX XX:XX:XX,XXX XXX WARNING - This is a warning message 2023-XX-XX XX:XX:XX,XXX XXX ERROR - This is an error message 2023-XX-XX XX:XX:XX,XXX XXX CRITICAL - This is a critical message
通过上述输出可以看出,虽然控制台只显示了WARNING及以上级别的消息(因为console_log的级别被设置为WARNING),但INFO级别的消息已经成功写入了ExampleLogger.log文件,这证明了Logger本身的级别设置是关键。
最佳实践与注意事项
- 始终设置Logger的级别:这是解决低级别日志不显示问题的核心。根据你的应用需求,将Logger的级别设置为你希望捕获的最低级别,例如logging.DEBUG或logging.INFO。
- 理解Logger与Handler的级别协同:Logger的级别是“总闸门”,Handler的级别是“分闸门”。日志消息必须先通过总闸门,再通过对应的分闸门才能被处理。
- 避免重复添加Handler:在多次调用同一个Logger的配置函数时,务必检查并移除已存在的Handler,如示例代码中的if logger.handlers: for handler in logger.handlers[:]: logger.removeHandler(handler),否则会导致日志重复输出。
- 根Logger (root Logger):如果你没有通过logging.getLogger('name')获取一个具名Logger,而是直接使用logging.debug()、logging.info()等函数,你实际上是在使用根Logger。根Logger的默认级别也是WARNING。你可以通过logging.basicConfig()来配置根Logger的级别和Handler。
- 日志级别选择:
- DEBUG: 详细的调试信息,通常只在开发阶段使用。
- INFO: 确认程序按预期运行的信息。
- WARNING: 潜在问题或非预期事件,但程序仍能正常运行。
- ERROR: 程序执行过程中发生的错误,导致某些功能无法正常进行。
- CRITICAL: 严重错误,程序可能无法继续运行。
通过正确理解并配置Logger实例的级别,你可以确保Python logging模块能够按照预期捕获和输出所有重要日志信息,从而更有效地进行程序调试和监控。
好了,本文到此结束,带大家了解了《Pythonlogging不显示INFO日志解决方法》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多文章知识!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
114 收藏
-
400 收藏
-
486 收藏
-
358 收藏
-
316 收藏
-
154 收藏
-
197 收藏
-
359 收藏
-
204 收藏
-
470 收藏
-
195 收藏
-
327 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习