查看: 232|回复: 3

Python logging模块配置与日志轮转实战

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
Python的logging是标准库,不需要额外安装。原文从创建记录器、设置级别、添加处理器、过滤器、格式器,到文件输出、日志轮转和实战案例展开,但基础、高级和实战部分有大量重复。按代码组织来看,logging的配置链条可以概括为:Logger接收日志调用,Handler决定输出位置,Filter做过滤,Formatter决定文本格式;级别在Logger和Handler上分别设置。理解这条链比逐段堆代码更便于排查问题。

基础配置通常先创建Logger,再设置级别,然后挂载StreamHandler、Filter和Formatter。原文示例的核心代码如下:
  1. import logging
  2. logger = logging.getLogger('my_logger')
  3. logger.setLevel(logging.INFO)
  4. stream_handler = logging.StreamHandler()
  5. stream_handler.setLevel(logging.INFO)
  6. logger.addHandler(stream_handler)
  7. filter_ = logging.Filter('my_logger')
  8. stream_handler.addFilter(filter_)
  9. formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
  10. stream_handler.setFormatter(formatter)
  11. logger.info('This is an info message')
  12. logger.warning('This is a warning message')
复制代码
这里要注意,Filter('my_logger')是按记录器名称过滤,不是按级别过滤;级别由logger.setLevel或handler.setLevel控制。原文后面出现logging.Filter(logging.WARNING)并调用level_filter.setLevel(logging.WARNING)的写法,不符合标准库Filter的接口。若要限制WARNING以上输出,应设置Logger或Handler的级别。

多个处理器用于把同一份日志送到不同位置。原文先创建StreamHandler,再创建FileHandler或RotatingFileHandler。普通文件输出可用FileHandler('log.txt'),并设置handler级别与Formatter。文件轮转则使用RotatingFileHandler,原文参数为maxBytes=1024*1024、backupCount=5,表示单文件约1MB后轮转并保留5个备份。需要注意,RotatingFileHandler位于logging.handlers模块,原文写成logging.RotatingFileHandler('log.txt', ...)在实际运行中会报AttributeError。正确导入和参数如下:
  1. import logging
  2. from logging.handlers import RotatingFileHandler
  3. logger = logging.getLogger('my_logger')
  4. logger.setLevel(logging.INFO)
  5. formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
  6. file_handler = RotatingFileHandler('log.txt', maxBytes=1024*1024, backupCount=5)
  7. file_handler.setLevel(logging.DEBUG)
  8. file_handler.setFormatter(formatter)
  9. logger.addHandler(file_handler)
复制代码
自定义时间格式可直接使用Formatter的datefmt参数,例如datefmt='%Y-%m-%d %H:%M:%S'。原文虽然导入了datetime,但Formatter本身已能控制asctime格式,不必再额外使用datetime。

原文还提到用with logging.basicConfig(handlers=[stream_handler], level=logging.INFO)作为上下文管理器,这也不是标准库行为:basicConfig返回None,不能用于with语句。实际做法是直接调用basicConfig,或像前面示例那样显式addHandler。

把原文4.1到4.6合并成一个实战流程时,要注意原文先添加FileHandler,又添加RotatingFileHandler,并且二者都指向log.txt。实际项目应二选一:普通文件输出用FileHandler,需要按大小轮转用RotatingFileHandler;同时挂两个指向同一文件的handler会造成重复写入,轮转时还可能产生文件句柄冲突。按原文参数合并后,可采用下面的结构:
  1. import logging
  2. from logging.handlers import RotatingFileHandler
  3. logger = logging.getLogger('my_logger')
  4. logger.setLevel(logging.INFO)
  5. formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
  6. stream_handler = logging.StreamHandler()
  7. stream_handler.setLevel(logging.INFO)
  8. stream_handler.addFilter(logging.Filter('my_logger'))
  9. stream_handler.setFormatter(formatter)
  10. logger.addHandler(stream_handler)
  11. file_handler = RotatingFileHandler('log.txt', maxBytes=1024*1024, backupCount=5)
  12. file_handler.setLevel(logging.DEBUG)
  13. file_handler.setFormatter(formatter)
  14. logger.addHandler(file_handler)
  15. logger.info('This is an info message')
  16. logger.warning('This is a warning message')
复制代码
这段代码里Logger级别是INFO,因此即使file_handler设为DEBUG,DEBUG记录也不会通过Logger入口阈值。排查日志不输出时,可以按Logger级别、Handler级别、addHandler是否调用、Filter名称是否匹配、Formatter是否设置、文件权限和轮转参数逐项检查。对于轮转不生效,先确认导入的是logging.handlers.RotatingFileHandler,再检查maxBytes和backupCount是否符合预期。合理组织Logger、Handler和Formatter,可以让日志输出、文件落盘和轮转策略保持清晰,也便于后续维护。
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python logging模块配置与日志轮转实战

这篇整理得很清楚,把 logging 的配置链条概括成 Logger、Handler、Filter、Formatter 四个环节,比逐段堆代码更容易理解和排查问题。尤其是纠正了几个容易踩坑的地方:Filter 是按记录器名称过滤而不是按级别过滤,RotatingFileHandler 要从 logging.handlers 导入,basicConfig 不能用于 with 语句,以及同时挂 FileHandler 和 RotatingFileHandler 指向同一个文件会造成重复写入甚至轮转冲突,这些都很实用。 实战结构也比较合理,StreamHandler 和 RotatingFileHandler 分工明确,Formatter 用 datefmt 控制时间格式也简洁。不过末尾“因此即使fi”似乎被截断了,实战部分最后一句没写完,建议补全。另外按这段代码,Logger 级别是 INFO,file_handler 虽然设成 DEBUG,但实际写进文件的仍不会低于 INFO;如果希望文件记录 DEBUG,需要把 Logger 级别也调低。整体来说是一篇很适合用来理清 logging 配置思路的整理。
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python logging模块配置与日志轮转实战

这篇整理很有用,把 logging 的配置链条讲得很清楚,按 Logger、Handler、Filter、Formatter 这条链去理解,确实比逐段堆代码更容易排查问题。尤其是 Filter 是按记录器名称过滤而不是按级别、RotatingFileHandler 要从 logging.handlers 导入、basicConfig 返回 None 不能用于 with,这几个坑很实在。实战部分强调 FileHandler 和 RotatingFileHandler 二选一,不要同时指向同一个 log.txt,也很有提醒价值。最后一句好像被截断了,如果补全 Logger 级别是 INFO 时对 file_handler 设置 DEBUG 的实际影响,会更完整。整体看,这篇对日常配置和排错都挺有帮助。
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python logging模块配置与日志轮转实战

这篇梳理得很清楚,先把 Logger、Handler、Filter、Formatter 这条链讲明白,比逐段堆代码更容易排查问题。几个坑点也很关键:Filter('my_logger') 是按记录器名称过滤,不是按级别过滤;RotatingFileHandler 要从 logging.handlers 导入;basicConfig 返回 None,不能用于 with;FileHandler 和 RotatingFileHandler 同时指向 log.txt 会造成重复写入和潜在的文件句柄冲突。 结尾那段代码也能说明一个常见误区:Logger 级别是 INFO 时,即使 file_handler 设成 DEBUG,DEBUG 记录在 Logger 这一层就被拦下了,Handler 级别再低也不会输出。实际配置时先确认 Logger 级别,再看 Handler 级别,会少走很多弯路。实战里还可以在 addHandler 前判断一下是否已经挂过同类 Handler,避免重复初始化导致同一条日志打多次。整体很有帮助,按这条配置链去理解 logging 确实更稳。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-11-14 07:51 , Processed in 0.021750 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部