python通过TimedRotatingFileHandler按时间切割日志


Posted in Python onJuly 17, 2019

通过TimedRotatingFileHandler按时间切割日志

线上跑了一个定时脚本,每天生成的日志文件都写在了一个文件中。但是日志信息不可能输出到单一的一个文件中。

原因有二:1.日志文件越来越大会影响系统的性能。2.日志文件格式不够清晰,比如我想看今天的日志,不太方便找到的今天的日志信息(即使对日志输出做了时间提示)

通过设置 TimedRotatingFileHandler 进行日志按周(W)、天(D)、时(H)、分(M)、秒(S)切割。

先看一个简单例子:

import time
import logging
import os
from logging import handlers
def _logging(**kwargs):
  level = kwargs.pop('level', None)
  filename = kwargs.pop('filename', None)
  datefmt = kwargs.pop('datefmt', None)
  format = kwargs.pop('format', None)
  if level is None:
    level = logging.DEBUG
  if filename is None:
    filename = 'default.log'
  if datefmt is None:
    datefmt = '%Y-%m-%d %H:%M:%S'
  if format is None:
    format = '%(asctime)s [%(module)s] %(levelname)s [%(lineno)d] %(message)s'
  log = logging.getLogger(filename)
  format_str = logging.Formatter(format, datefmt)
  # backupCount 保存日志的数量,过期自动删除
  # when 按什么日期格式切分(这里方便测试使用的秒)
  th = handlers.TimedRotatingFileHandler(filename=filename, when='S', backupCount=3, encoding='utf-8')
  th.setFormatter(format_str)
  th.setLevel(logging.INFO)
  log.addHandler(th)
  log.setLevel(level)
  return log
os.makedirs("./logs", exist_ok=True)
logger = _logging(filename='./logs/default.log')
if __name__ == '__main__':
  while True:
    time.sleep(0.1)
    logger.info('哈哈哈')

结果如下:

python通过TimedRotatingFileHandler按时间切割日志

上述代码可以正常运行,而且也可以生成固定的日志个数,但是有一个问题,生成的日志文件格式是你的 文件名+时间 的格式,没有设置时间的话默认设置到了秒(这里是按秒切割)

修改日志格式后缀名称:

# 在上述代码中加入
def namer(filename):
  return filename.split('default.')
th.namer = namer
# 设置为S,默认的suffix为 Y-%m-%d_%H-%M-%S
th.suffix = "%Y-%m-%d_%H-%M-%S.log"
# 为了看的更视觉效果,可以显示在控制台答应
cmd = logging.StreamHandler()
cmd.setFormatter(format_str)
cmd.setLevel(level)
log.addHandler(cmd)

运行结果:

python通过TimedRotatingFileHandler按时间切割日志

名字好像可以了,但是日志好像没有起到自动删除的目的啊,而且也没在之前的log文件夹了。

来看看源码:

def getFilesToDelete(self):
    """
    Determine the files to delete when rolling over.

    More specific than the earlier method, which just used glob.glob().
    """
    dirName, baseName = os.path.split(self.baseFilename)
    fileNames = os.listdir(dirName)
    result = []
    prefix = baseName + "."
    plen = len(prefix)
    for fileName in fileNames:
      if fileName[:plen] == prefix:
        suffix = fileName[plen:]
        if self.extMatch.match(suffix):
          result.append(os.path.join(dirName, fileName))
    if len(result) < self.backupCount:
      result = []
    else:
      result.sort()
      result = result[:len(result) - self.backupCount]
    return result

这是它的删除逻辑,关键是通过 . 前面的字段判断是否重复,当有特定的重复数后开始删除。

所以问题来了,要么自己去重写源码,要么就只能用 default.日期.log 这种格式了。

附上平时使用的日志代码

import logging
import os
from logging import handlers
def _logging(**kwargs):
  level = kwargs.pop('level', None)
  filename = kwargs.pop('filename', None)
  datefmt = kwargs.pop('datefmt', None)
  format = kwargs.pop('format', None)
  if level is None:
    level = logging.DEBUG
  if filename is None:
    filename = 'default.log'
  if datefmt is None:
    datefmt = '%Y-%m-%d %H:%M:%S'
  if format is None:
    format = '%(asctime)s [%(module)s] %(levelname)s [%(lineno)d] %(message)s'
  log = logging.getLogger(filename)
  format_str = logging.Formatter(format, datefmt)
  def namer(filename):
    return filename.split('default.')[1]
  # cmd = logging.StreamHandler()
  # cmd.setFormatter(format_str)
  # cmd.setLevel(level)
  # log.addHandler(cmd)
  os.makedirs("./debug/logs", exist_ok=True)
  th_debug = handlers.TimedRotatingFileHandler(filename="./debug/" + filename, when='D', backupCount=3,
                         encoding='utf-8')
  # th_debug.namer = namer
  th_debug.suffix = "%Y-%m-%d.log"
  th_debug.setFormatter(format_str)
  th_debug.setLevel(logging.DEBUG)
  log.addHandler(th_debug)
  th = handlers.TimedRotatingFileHandler(filename=filename, when='D', backupCount=3, encoding='utf-8')
  # th.namer = namer
  th.suffix = "%Y-%m-%d.log"
  th.setFormatter(format_str)
  th.setLevel(logging.INFO)
  log.addHandler(th)
  log.setLevel(level)
  return log
os.makedirs('./logs', exist_ok=True)
logger = _logging(filename='./logs/default')

总结

以上所述是小编给大家介绍的python通过TimedRotatingFileHandler按时间切割日志,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
python 字符串split的用法分享
Mar 23 Python
python使用smtplib模块通过gmail实现邮件发送的方法
May 08 Python
用python记录运行pid,并在需要时kill掉它们的实例
Jan 16 Python
Python标准库sched模块使用指南
Jul 06 Python
Python3.4编程实现简单抓取爬虫功能示例
Sep 14 Python
python自动12306抢票软件实现代码
Feb 24 Python
使用Python操作FTP实现上传和下载的方法
Apr 01 Python
python语言基本语句用法总结
Jun 11 Python
Python 分发包中添加额外文件的方法
Aug 16 Python
OpenCV4.1.0+VS2017环境配置的方法步骤
Jul 09 Python
Python基于xlrd模块处理合并单元格
Jul 28 Python
将不规则的Python多维数组拉平到一维的方法实现
Jan 11 Python
python递归法实现简易连连看小游戏
Mar 25 #Python
django2笔记之路由path语法的实现
Jul 17 #Python
Django之创建引擎索引报错及解决详解
Jul 17 #Python
python实现连连看辅助之图像识别延伸
Jul 17 #Python
Django 路由控制的实现
Jul 17 #Python
详解python实现数据归一化处理的方式:(0,1)标准化
Jul 17 #Python
简单了解django索引的相关知识
Jul 17 #Python
You might like
php 获取完整url地址
2008/12/20 PHP
关于Iframe如何跨域访问Cookie和Session的解决方法
2013/04/15 PHP
详谈PHP编码转换问题
2015/07/28 PHP
Riot.js 快速的JavaScript单元测试框架
2009/11/09 Javascript
ASP.NET jQuery 实例17 通过使用jQuery validation插件校验ListBox
2012/02/03 Javascript
怎么清空javascript数组
2013/05/11 Javascript
js jq 单击和双击区分示例介绍
2013/11/05 Javascript
AngularJS中的$watch(),$digest()和$apply()区分
2016/04/04 Javascript
js智能获取浏览器版本UA信息的方法
2016/08/08 Javascript
JavaScript队列、优先队列与循环队列
2016/11/14 Javascript
javascript内存分配原理实例分析
2017/04/10 Javascript
vue学习笔记之指令v-text &amp;&amp; v-html &amp;&amp; v-bind详解
2017/05/12 Javascript
用nodejs实现json和jsonp服务的方法
2017/08/25 NodeJs
JavaScript 自定义事件之我见
2017/09/25 Javascript
webpack之devtool详解
2018/02/10 Javascript
webpack配置打包后图片路径出错的解决
2018/04/26 Javascript
JavaScript实现淘宝京东6位数字支付密码效果
2018/08/18 Javascript
vue-cli 脚手架基于Nightwatch的端到端测试环境的过程
2018/09/30 Javascript
vue组件tabbar使用方法详解
2018/11/06 Javascript
js中值引用和地址引用实例分析
2019/06/21 Javascript
jQuery 淡入/淡出效果函数用法分析
2020/05/19 jQuery
Javascript原型链及instanceof原理详解
2020/05/25 Javascript
js实现列表按字母排序
2020/08/11 Javascript
vue实现广告栏上下滚动效果
2020/11/26 Vue.js
[39:11]DOTA2上海特级锦标赛C组资格赛#2 LGD VS Newbee第二局
2016/02/28 DOTA
[02:41]辉夜杯现场一家三口 “我爸玩风行 我玩血魔”
2015/12/27 DOTA
python实现RSA加密(解密)算法
2016/02/17 Python
python下实现二叉堆以及堆排序的示例
2017/09/29 Python
Python实现随机创建电话号码的方法示例
2018/12/07 Python
如何为Python终端提供持久性历史记录
2019/09/03 Python
Python 实现判断图片格式并转换,将转换的图像存到生成的文件夹中
2020/01/13 Python
Python通过两个dataframe用for循环求笛卡尔积
2020/04/29 Python
让ie浏览器成为支持html5的浏览器的解决方法(使用html5shiv)
2014/04/08 HTML / CSS
英国手机零售商:Carphone Warehouse
2018/06/06 全球购物
经典婚礼主持词
2014/03/13 职场文书
2014年教师个人工作总结
2014/11/10 职场文书