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多线程结合队列下载百度音乐的方法
Jul 27 Python
Python 模板引擎的注入问题分析
Jan 01 Python
python select.select模块通信全过程解析
Sep 20 Python
对Python3中的input函数详解
Apr 22 Python
如何用Python合并lmdb文件
Jul 02 Python
flask入门之表单的实现
Jul 18 Python
Python中时间datetime的处理与转换用法总结
Feb 18 Python
Python 实现Serial 与STM32J进行串口通讯
Dec 18 Python
Python安装whl文件过程图解
Feb 18 Python
Python unittest单元测试框架及断言方法
Apr 15 Python
利用python实现后端写网页(flask框架)
Feb 28 Python
Python jiaba库的使用详解
Nov 23 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
PHP4实际应用经验篇(8)
2006/10/09 PHP
如何从一个php文件向另一个地址post数据,不用表单和隐藏的变量的
2007/03/06 PHP
PHP常用代码大全(新手入门必备)
2010/06/29 PHP
php入门学习知识点二 PHP简单的分页过程与原理
2011/07/14 PHP
windows下配置apache+php+mysql时出现问题的处理方法
2014/06/20 PHP
php发送邮件的问题详解
2015/06/22 PHP
php开发微信支付获取用户地址
2015/10/04 PHP
基于PHP常用文件函数和目录函数整理
2017/08/17 PHP
PDO::_construct讲解
2019/01/27 PHP
PHP INT类型在内存中占字节详解
2019/07/20 PHP
javascript英文日期(有时间)选择器
2007/05/02 Javascript
JS操作数据库的实例代码
2013/10/17 Javascript
Javascript遍历table中的元素示例代码
2014/07/08 Javascript
JavaScript中join()方法的使用简介
2015/06/09 Javascript
JS简单模拟触发按钮点击功能的方法
2015/11/30 Javascript
详解Vue2.0之去掉组件click事件的native修饰
2017/04/20 Javascript
seajs中模块依赖的加载处理实例分析
2017/10/10 Javascript
vue router动态路由下让每个子路由都是独立组件的解决方案
2018/04/24 Javascript
Nodejs Express 通过log4js写日志到Logstash(ELK)
2018/08/30 NodeJs
Vue项目路由刷新的实现代码
2019/04/17 Javascript
python实现字符串和日期相互转换的方法
2015/05/13 Python
Python实现程序的单一实例用法分析
2015/06/03 Python
分享一下Python 开发者节省时间的10个方法
2015/10/02 Python
python链接oracle数据库以及数据库的增删改查实例
2018/01/30 Python
Python文件常见操作实例分析【读写、遍历】
2018/12/10 Python
决策树剪枝算法的python实现方法详解
2019/09/18 Python
如何在Win10系统使用Python3连接Hive
2020/10/15 Python
会计与审计毕业生自荐信范文
2013/12/30 职场文书
自我鉴定三原则
2014/01/13 职场文书
综治宣传月活动总结
2014/04/28 职场文书
品质标语大全
2014/06/21 职场文书
水污染治理工程专业自荐信
2014/06/21 职场文书
2015年科协工作总结
2015/05/19 职场文书
格列佛游记读书笔记
2015/06/30 职场文书
2015年迎新晚会策划书
2015/07/16 职场文书
Java无向树分析 实现最小高度树
2022/04/09 Javascript