Python logging模块异步线程写日志实现过程解析


Posted in Python onJune 30, 2020

通过logging模块,重写一个logging2模块,独立开启线程,将待写的日志信息异步放入队列,做到日志输出不影响主流程性能,环境python3.8

logging2.py

import os
import threading
import queue
import time
import datetime
import logging
from logging.handlers import RotatingFileHandler

class logging2(threading.Thread):
  AQueue = queue.Queue(100000)
  nPID = os.getpid()
  Adt = datetime.datetime.now().strftime('%Y%m%d')
  nCount = 1
  
  def __init__(self, threadID, name, module, logLevel):
    threading.Thread.__init__(self)
    self.threadID = threadID
    self.name = name
    self.module = module
    
    print("set loglevel: [%s]" % (logLevel) )
    formatter = logging.Formatter('%(asctime)s|%(name)s|%(process)d|%(levelname)s|%(message)s')
    logfile = "log_" + self.module + "_" + str(logging2.nPID) + "_" + str(logging2.Adt) + ".log"
    self.logger = logging.getLogger(__name__)
    
    self.rHandler = RotatingFileHandler(logfile, maxBytes = 10*1024*1024, backupCount = 10)
    self.rHandler.setFormatter(formatter)
    
    self.console = logging.StreamHandler()  
    self.console.setFormatter(formatter)
    
    if logLevel == 'DEBUG' :
      self.logger.setLevel(level = logging.DEBUG)
      self.rHandler.setLevel(logging.DEBUG)
      self.console.setLevel(logging.DEBUG)
    elif logLevel == 'INFO' :
      self.logger.setLevel(level = logging.INFO)
      self.rHandler.setLevel(logging.INFO)
      self.console.setLevel(logging.INFO)
    elif logLevel == 'WARNING' :
      self.logger.setLevel(level = logging.WARN)
      self.rHandler.setLevel(logging.WARN)
      self.console.setLevel(logging.WARN)
    elif logLevel == 'ERROR' :
      self.logger.setLevel(level = logging.ERROR)
      self.rHandler.setLevel(logging.ERROR)
      self.console.setLevel(logging.ERROR)    

    self.logger.addHandler(self.rHandler)
    self.logger.addHandler(self.console)    

  #如果跨天了,则重新生成新的文件名
  def reSetLog(self):
    AdtTemp = datetime.datetime.now().strftime('%Y%m%d')
    #比较新的时间
    if AdtTemp == logging2.Adt:
      return(True)
      
    logging2.Adt = AdtTemp
    logfile = "log_" + self.module + "_" + str(logging2.nPID) + "_" + str(AdtTemp) + ".log"
    self.rHandler = RotatingFileHandler(logfile, maxBytes = 1*1024, backupCount = 10)
    
    self.logger.addHandler(self.rHandler)
    self.logger.addHandler(self.console)  
    logging2.nCount += 1
    
  def run(self):
    print ("开启日志线程:" + self.name)
    i = 0
    while True:
      #data = "queue test data"
      #debug(data)
      #print("Queuesize: %s" % (logging2.AQueue.qsize()))
      self.reSetLog()
      if logging2.AQueue.empty() == False:
        #从队列获取日志消息
        data = logging2.AQueue.get()
        #解析日志消息,格式:日志级别,内容
        level = list(data.keys())[0]
        content = data.get(level)
        #把内容按分隔符|解析成list传入参数
        lstContent = list(content.split('|'))
        if level == 'DEBUG' :
          self.logger.debug(*lstContent)
        elif level == 'INFO' :
          self.logger.info(*lstContent)
        elif level == 'WARNING' :
          self.logger.warn(*lstContent)
        elif level == 'ERROR' :
          self.logger.error(*lstContent)
      else:
        time.sleep(0.5)

    print ("退出线程:" + self.name)  
  
def debug(*content):  
  logMsg = ""
  #传入多个参数用竖线分隔符分开
  for i in range(len(content)):
    if i == len(content)-1:
      logMsg += content[i]
    else:
      logMsg += content[i]+"|"
  logging2.AQueue.put({'DEBUG':logMsg})
      
def info(*content):
  logMsg = ""
  for i in range(len(content)):
    if i == len(content)-1:
      logMsg += content[i]
    else:
      logMsg += content[i]+"|"
  logging2.AQueue.put({'INFO':logMsg})
        
def warn(*content):
  logMsg = ""
  for i in range(len(content)):
    if i == len(content)-1:
      logMsg += content[i]
    else:
      logMsg += content[i]+"|"
  logging2.AQueue.put({'WARNING':logMsg})
    
def error(*content):
  logMsg = ""
  for i in range(len(content)):
    if i == len(content)-1:
      logMsg += content[i]
    else:
      logMsg += content[i]+"|"
  logging2.AQueue.put({'ERROR':logMsg})
          
def init(module, level):
  # 创建新线程
  thread1 = logging2(1, "Thread-log", module, level)
  # 开启新线程
  thread1.start()
#  thread1.join()

测试桩logMain.py

import sys
import os
import time
import threading

if __name__ == '__main__':
  import logging2
  logging2.init("logMain", "DEBUG")
  
  teststr = "22222"
  
  while True:
    logging2.debug('this is a debug log test [%s] ', teststr)
    logging2.info('this is a info log test [%s] [%s]', teststr, teststr)
    logging2.warn('this is a warn log test')
    logging2.error('this is a error log test')
    #time.sleep(0.1)
  
  
  print(threading.enumerate())
  
  print('press ctrl_c to exit')

测试结果

生成日志文件:

-rw-rw-r--. 1 zxl zxl 10152463 6月 24 17:52 log_logMain_57554_20200624.log

文件内容如下:

Python logging模块异步线程写日志实现过程解析

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python网络爬虫采集联想词示例
Feb 11 Python
用Python的Flask框架结合MySQL写一个内存监控程序
Nov 07 Python
利用Python获取操作系统信息实例
Sep 02 Python
用Python将动态GIF图片倒放播放的方法
Nov 02 Python
python 3.5下xadmin的使用及修复源码bug
May 10 Python
关于Django外键赋值问题详解
Aug 13 Python
关于Python数据结构中字典的心得
Dec 04 Python
python实现画圆功能
Jan 25 Python
Python弹出输入框并获取输入值的实例
Jun 18 Python
基于Python词云分析政府工作报告关键词
Jun 02 Python
关于tensorflow softmax函数用法解析
Jun 30 Python
详解win10下pytorch-gpu安装以及CUDA详细安装过程
Jan 28 Python
浅谈多卡服务器下隐藏部分 GPU 和 TensorFlow 的显存使用设置
Jun 30 #Python
Tensorflow中批量读取数据的案列分析及TFRecord文件的打包与读取
Jun 30 #Python
使用Tensorflow-GPU禁用GPU设置(CPU与GPU速度对比)
Jun 30 #Python
keras的backend 设置 tensorflow,theano操作
Jun 30 #Python
浅谈TensorFlow中读取图像数据的三种方式
Jun 30 #Python
python中 _、__、__xx__()区别及使用场景
Jun 30 #Python
Django实现内容缓存实例方法
Jun 30 #Python
You might like
虹吸壶煮咖啡26个注意事项
2021/03/03 冲泡冲煮
php中文字符截取防乱码
2008/03/28 PHP
php mysql Errcode: 28 终极解决方法
2009/07/01 PHP
PHP count()函数讲解
2019/02/03 PHP
javascript AutoScroller 函数类
2009/05/29 Javascript
2012年开发人员的16款新鲜的jquery插件体验分享
2012/12/28 Javascript
Jquery 复选框取值兼容FF和IE8(测试有效)
2013/10/29 Javascript
JS连连看源码完美注释版(推荐)
2013/12/09 Javascript
js 通过cookie实现刷新不变化树形菜单
2014/10/30 Javascript
详解JavaScript中的构造器Constructor模式
2016/01/14 Javascript
React实现点击删除列表中对应项
2017/01/10 Javascript
基于vue中对鼠标划过事件的处理方式详解
2018/08/22 Javascript
微信小程序实现随机验证码功能
2018/12/20 Javascript
微信小程序实现bindtap等事件传参
2019/04/08 Javascript
vue给对象动态添加属性和值的实例
2019/09/09 Javascript
node-red File读取好保存实例讲解
2019/09/11 Javascript
JS访问对象两种方式区别解析
2020/08/29 Javascript
python实现巡检系统(solaris)示例
2014/04/02 Python
Python模拟随机游走图形效果示例
2018/02/06 Python
python实现word 2007文档转换为pdf文件
2018/03/15 Python
PyQt5每天必学之单行文本框
2018/04/19 Python
python如何生成网页验证码
2018/07/28 Python
python 自定义装饰器实例详解
2019/07/20 Python
Python3 filecmp模块测试比较文件原理解析
2020/03/23 Python
使用Pycharm分段执行代码
2020/04/15 Python
python属于软件吗
2020/06/18 Python
python创建文本文件的简单方法
2020/08/30 Python
Ivory Isle Designs美国/加拿大:婚礼和活动文具公司
2018/08/21 全球购物
市级文明单位申报材料
2014/05/07 职场文书
娱乐节目策划方案
2014/06/10 职场文书
银行竞聘报告范文
2014/11/06 职场文书
2016新年致辞
2015/08/01 职场文书
2019单位介绍信怎么写
2019/06/24 职场文书
立秋之描写立秋的作文(五年级)
2019/08/08 职场文书
Redis中key的过期删除策略和内存淘汰机制
2022/04/12 Redis
nginx 添加http_stub_status_module模块
2022/05/25 Servers