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中的闭包实例详解
Aug 29 Python
python中反射用法实例
Mar 27 Python
Python数字图像处理之霍夫线变换实现详解
Jan 12 Python
python判断所输入的任意一个正整数是否为素数的两种方法
Jun 27 Python
Python命令行参数解析工具 docopt 安装和应用过程详解
Sep 26 Python
Python使用Pandas库常见操作详解
Jan 16 Python
Python : turtle色彩控制实例详解
Jan 19 Python
Python表达式的优先级详解
Feb 18 Python
Python基于Dlib的人脸识别系统的实现
Feb 26 Python
Pycharm最常用的快捷键及使用技巧
Mar 05 Python
python 错误处理 assert详解
Apr 20 Python
Opencv常见图像格式Data Type及代码实例
Nov 02 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
codeigniter中实现一次性加载多个view的方法
2015/03/20 PHP
PHP基于phpqrcode生成带LOGO图像的二维码实例
2015/07/10 PHP
PHP函数nl2br()与自定义函数nl2p()换行用法分析
2016/04/02 PHP
PHP排序算法之堆排序(Heap Sort)实例详解
2018/04/21 PHP
Javascript String.replace的妙用
2009/09/08 Javascript
Jquery 最近浏览过的商品的功能实现代码
2010/05/14 Javascript
基于jquery的无刷新分页技术
2011/06/11 Javascript
jquery 表格的增行删行实现思路
2013/03/21 Javascript
处理及遍历XML文档DOM元素属性及方法整理
2013/08/23 Javascript
JS中把字符转成ASCII值的函数示例代码
2013/11/21 Javascript
基于HTML+CSS,jQuery编写的简易计算器后续(添加了键盘监听)
2016/01/05 Javascript
angular2倒计时组件使用详解
2017/01/12 Javascript
vue判断input输入内容全是空格的方法
2018/03/02 Javascript
解决koa2 ctx.render is not a function报错问题
2018/08/07 Javascript
详解js获取video任意时间的画面截图
2019/04/17 Javascript
微信小程序 行的删除和增加操作实现详解
2019/09/29 Javascript
使用 Vue-TCB 快速在 Vue 应用中接入云开发的方法
2020/02/10 Javascript
JS实现网页时钟特效
2020/03/25 Javascript
Windows下Python使用Pandas模块操作Excel文件的教程
2016/05/31 Python
利用Python开发微信支付的注意事项
2016/08/19 Python
Python结巴中文分词工具使用过程中遇到的问题及解决方法
2017/04/15 Python
python装饰器-限制函数调用次数的方法(10s调用一次)
2018/04/21 Python
python3实现逐字输出的方法
2019/01/23 Python
Python 实现域名解析为ip的方法
2019/02/14 Python
详解Python实现进度条的4种方式
2020/01/15 Python
Python面向对象多态实现原理及代码实例
2020/09/16 Python
一款CSS3实现多功能下拉菜单(带分享按)的教程
2014/11/05 HTML / CSS
如何在Canvas中添加事件的方法示例
2019/05/21 HTML / CSS
荷兰演唱会和体育比赛订票网站:viagogo荷兰
2018/04/08 全球购物
致全体运动员广播稿
2014/02/01 职场文书
班级文化建设标语
2014/06/23 职场文书
教师节简报
2015/07/20 职场文书
班级元旦晚会开幕词
2016/03/04 职场文书
送给教师们,到底该如何写好教学反思?
2019/07/02 职场文书
在HTML中引入CSS的几种方式介绍
2021/12/06 HTML / CSS
深入理解pytorch库的dockerfile
2022/06/10 Python