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使用os模块的os.walk遍历文件夹示例
Jan 27 Python
Python迭代和迭代器详解
Nov 10 Python
通过python+selenium3实现浏览器刷简书文章阅读量
Dec 26 Python
python3判断url链接是否为404的方法
Aug 10 Python
python实现三次样条插值
Dec 17 Python
Python实现的排列组合、破解密码算法示例
Apr 12 Python
关于pytorch中网络loss传播和参数更新的理解
Aug 20 Python
基于numpy中的expand_dims函数用法
Dec 18 Python
Pyecharts地图显示不完成问题解决方案
May 11 Python
基于Python绘制美观动态圆环图、饼图
Jun 03 Python
Python实战之用tkinter库做一个鼠标模拟点击器
Apr 27 Python
教你利用Selenium+python自动化来解决pip使用异常
May 20 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
PHP函数utf8转gb2312编码
2006/12/21 PHP
深入理解PHP中的count函数
2016/05/31 PHP
jquery $.ajax入门应用一
2008/11/19 Javascript
JavaScript对象链式操作代码(jquery)
2010/07/04 Javascript
jQuery模拟点击A标记示例参考
2014/04/17 Javascript
jquery进行数组遍历如何跳出当前的each循环
2014/06/05 Javascript
Jquery操作Ajax方法小结
2015/11/29 Javascript
js操作cookie保存浏览记录的方法
2015/12/25 Javascript
js实现上传图片及时预览
2016/05/07 Javascript
IE8利用自带的setCapture和releaseCapture解决iframe的拖拽事件方法
2016/10/25 Javascript
jQuery插件FusionCharts绘制ScrollColumn2D图效果示例【附demo源码下载】
2017/03/22 jQuery
通过学习bootstrop导航条学会修改bootstrop颜色基调
2017/06/11 Javascript
Vue.js中关于侦听器(watch)的高级用法示例
2018/05/02 Javascript
基于webpack4搭建的react项目框架的方法
2018/06/30 Javascript
微信小程序云开发 生成带参小程序码流程
2019/05/18 Javascript
微信小程序后端(java)开发流程的详细步骤
2019/11/13 Javascript
Vuex实现数据共享的方法
2019/12/20 Javascript
让mocha支持ES6模块的方法实现
2020/01/14 Javascript
jquery实现拖拽小方块效果
2020/12/10 jQuery
python3设计模式之简单工厂模式
2017/10/17 Python
centos 安装python3.6环境并配置虚拟环境的详细教程
2018/02/22 Python
Python常用的json标准库
2019/02/19 Python
pandas 数据索引与选取的实现方法
2019/06/21 Python
python简单的三元一次方程求解实例
2020/04/02 Python
pycharm下pyqt4安装及环境配置的教程
2020/04/24 Python
详解Python遍历列表时删除元素的正确做法
2021/01/07 Python
路易威登和香奈儿手袋:LuxeDH
2017/01/12 全球购物
澳大利亚排名第一的在线酒类商店:MyBottleShop
2018/04/26 全球购物
三个儿子教学反思
2014/02/03 职场文书
总经理助理的职责
2014/03/14 职场文书
技术股份合作协议书
2014/10/05 职场文书
幼儿园六一儿童节演讲稿
2015/03/19 职场文书
如何利用js在两个html窗口间通信
2021/04/27 Javascript
Vue过滤器(filter)实现及应用场景详解
2021/06/15 Vue.js
Python中的嵌套循环详情
2022/03/23 Python
SpringBoot详解执行过程
2022/07/15 Java/Android