python的logging库中TimedRotatingFileHandler类问题

2023-11-20 22:38

本文主要是介绍python的logging库中TimedRotatingFileHandler类问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文网址:http://www.5dcode.com/?p=545

第一次用python,第一次用logging,第一次用TimedRotatingFileHandler,居然发现了其中的BUG,记录下吧。

      用TimedRotatingFileHandler的目的是让其自动在日志文件名后面加上日期时间,可以按秒、分、时、天、周或者其倍数来设置,BUG出现的场景是:手动设置时间,并把时间往未来时间调(比如把2012-03-15调成2014-03-15),这时就出问题了,这时产生每条日志后会产生一个日志文件,这并不是我们想要的效果,如果把当前时间再往历史时间调(比如把2012-03-15调成2010-03-15),这时也会产生问题:所有产生的日志都会记录到一个没有日期后缀的文件,并不会按日期分类。如果时间是正确的并按正常的流程走并不会产生问题,所以想看看logging是怎么实现的,看了其源码:C:\Python25\Lib\logging\handlers.py,果然不出所料,它的设计是有问题的,根本不考虑手动调时间或者时间可能不对需要同步的情况:

  1. def shouldRollover(self, record):
  2.         """
  3.         Determine if rollover should occur
  4.  
  5.         record is not used, as we are just comparing times, but it is needed so
  6.         the method siguratures are the same
  7.         """
  8.         t = int(time.time())
  9.         if t >= self.rolloverAt:
  10.             return 1
  11.         #print "No need to rollover: %d, %d" % (t, self.rolloverAt)
  12.         return 0
  13.  
  14.     def doRollover(self):
  15.         """
  16.         do a rollover; in this case, a date/time stamp is appended to the filename
  17.         when the rollover happens.  However, you want the file to be named for the
  18.         start of the interval, not the current time.  If there is a backup count,
  19.         then we have to get a list of matching filenames, sort them and remove
  20.         the one with the oldest suffix.
  21.         """
  22.         self.stream.close()
  23.         # get the time that this sequence started at and make it a TimeTuple
  24.         t = self.rolloverAt - self.interval
  25.         timeTuple = time.localtime(t)
  26.         dfn = self.baseFilename + "." + time.strftime(self.suffix, timeTuple)
  27.         if os.path.exists(dfn):
  28.             os.remove(dfn)
  29.         os.rename(self.baseFilename, dfn)
  30.         if self.backupCount > 0:
  31.             # find the oldest log file and delete it
  32.             s = glob.glob(self.baseFilename + ".20*")
  33.             if len(s) > self.backupCount:
  34.                 s.sort()
  35.                 os.remove(s[0])
  36.         #print "%s -> %s" % (self.baseFilename, dfn)
  37.         if self.encoding:
  38.             self.stream = codecs.open(self.baseFilename, 'w', self.encoding)
  39.         else:
  40.             self.stream = open(self.baseFilename, 'w')
  41.         self.rolloverAt = self.rolloverAt + self.interval

第9行判断中只判断时间大的情况,并没有判断时间小的情况,第41行中self.rolloverAt永远是上一次的值加上self.interval,如果时间往大的调的话,第9行判断就会永远是True,所以就会产生问题,如果时间往小的调,第9行判断就会永远是False,也会产生问题。上面的python版本是2.5.4,再看最新的版本:3.1,这个版本修复了def doRollover(self),但并没有修复def shouldRollover(self, record),所以综合这两个版本的考虑,还是自己来实现吧,修复之后的代码如下(测试成功通过):

 

  1. def shouldRollover(self, record):
  2.         """
  3.         Determine if rollover should occur
  4.  
  5.         record is not used, as we are just comparing times, but it is needed so
  6.         the method siguratures are the same
  7.         """
  8.         t = int(time.time())
  9.         #print "self.rolloverAt: %d. currentTime: %d." % (self.rolloverAt, t)
  10.         #start: recompare slef.rolloverAt, Modify by 5dcode. 2012-03-14 
  11.         if t >= self.rolloverAt or t < (self.rolloverAt - self.interval):
  12.             return 1
  13.         #end: recompare slef.rolloverAt, Modify by 5dcode. 2012-03-14 
  14.         #print "No need to rollover: %d, %d" % (t, self.rolloverAt)
  15.         return 0
  16.  
  17.     def doRollover(self):
  18.         """
  19.         do a rollover; in this case, a date/time stamp is appended to the filename
  20.         when the rollover happens.  However, you want the file to be named for the
  21.         start of the interval, not the current time.  If there is a backup count,
  22.         then we have to get a list of matching filenames, sort them and remove
  23.         the one with the oldest suffix.
  24.         """
  25.         self.stream.close()
  26.         # get the time that this sequence started at and make it a TimeTuple
  27.         t = self.rolloverAt - self.interval
  28.         timeTuple = time.localtime(t)
  29.         dfn = self.baseFilename + "." + time.strftime(self.suffix, timeTuple)
  30.         if os.path.exists(dfn):
  31.             os.remove(dfn)
  32.         os.rename(self.baseFilename, dfn)
  33.         if self.backupCount > 0:
  34.             # find the oldest log file and delete it
  35.             s = glob.glob(self.baseFilename + ".20*")
  36.             if len(s) > self.backupCount:
  37.                 s.sort()
  38.                 os.remove(s[0])
  39.         #print "%s -> %s" % (self.baseFilename, dfn)
  40.         if self.encoding:
  41.             self.stream = codecs.open(self.baseFilename, 'w', self.encoding)
  42.         else:
  43.             self.stream = open(self.baseFilename, 'w')
  44.         
  45.         #start: recompute self.rolloverAt, Modify by 5dcode. 2012-03-14 
  46.         currentTime = int(time.time())
  47.         newRolloverAt = currentTime + self.interval
  48.         if self.when == 'MIDNIGHT' or self.when.startswith('W'):
  49.             # This could be done with less code, but I wanted it to be clear
  50.             t = time.localtime(currentTime)
  51.             currentHour = t[3]
  52.             currentMinute = t[4]
  53.             currentSecond = t[5]
  54.             # r is the number of seconds left between now and midnight
  55.             r = _MIDNIGHT - ((currentHour * 60 + currentMinute) * 60 +
  56.                     currentSecond)
  57.             newRolloverAt = currentTime + r
  58.         #newRolloverAt = self.computeRollover(currentTime)
  59.         while newRolloverAt <= currentTime:
  60.             newRolloverAt = newRolloverAt + self.interval
  61.         #If DST changes and midnight or weekly rollover, adjust for this.
  62.         if self.when == 'MIDNIGHT' or self.when.startswith('W'):
  63.             dstNow = time.localtime(currentTime)[-1]
  64.             dstAtRollover = time.localtime(newRolloverAt)[-1]
  65.             if dstNow != dstAtRollover:
  66.                 if not dstNow:  # DST kicks in before next rollover, so we need to deduct an hour
  67.                     newRolloverAt = newRolloverAt - 3600
  68.                 else:           # DST bows out before next rollover, so we need to add an hour
  69.                     newRolloverAt = newRolloverAt + 3600
  70.         self.rolloverAt = newRolloverAt
  71.         #print "self.rolloverAt: %d." % self.rolloverAt
  72.         #end: recompute self.rolloverAt, Modify by 5dcode. 2012-03-14

 

 

 

 

这篇关于python的logging库中TimedRotatingFileHandler类问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/397941

相关文章

Windows环境下解决Matplotlib中文字体显示问题的详细教程

《Windows环境下解决Matplotlib中文字体显示问题的详细教程》本文详细介绍了在Windows下解决Matplotlib中文显示问题的方法,包括安装字体、更新缓存、配置文件设置及编码調整,并... 目录引言问题分析解决方案详解1. 检查系统已安装字体2. 手动添加中文字体(以SimHei为例)步骤

SpringSecurity整合redission序列化问题小结(最新整理)

《SpringSecurity整合redission序列化问题小结(最新整理)》文章详解SpringSecurity整合Redisson时的序列化问题,指出需排除官方Jackson依赖,通过自定义反序... 目录1. 前言2. Redission配置2.1 RedissonProperties2.2 Red

nginx 负载均衡配置及如何解决重复登录问题

《nginx负载均衡配置及如何解决重复登录问题》文章详解Nginx源码安装与Docker部署,介绍四层/七层代理区别及负载均衡策略,通过ip_hash解决重复登录问题,对nginx负载均衡配置及如何... 目录一:源码安装:1.配置编译参数2.编译3.编译安装 二,四层代理和七层代理区别1.二者混合使用举例

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

Python办公自动化实战之打造智能邮件发送工具

《Python办公自动化实战之打造智能邮件发送工具》在数字化办公场景中,邮件自动化是提升工作效率的关键技能,本文将演示如何使用Python的smtplib和email库构建一个支持图文混排,多附件,多... 目录前言一、基础配置:搭建邮件发送框架1.1 邮箱服务准备1.2 核心库导入1.3 基础发送函数二、

Python包管理工具pip的升级指南

《Python包管理工具pip的升级指南》本文全面探讨Python包管理工具pip的升级策略,从基础升级方法到高级技巧,涵盖不同操作系统环境下的最佳实践,我们将深入分析pip的工作原理,介绍多种升级方... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert