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生成器的使用方法
Nov 21 Python
python实现根据月份和日期得到星座的方法
Mar 27 Python
Python中selenium实现文件上传所有方法整理总结
Apr 01 Python
python3+PyQt5泛型委托详解
Apr 24 Python
一些Centos Python 生产环境的部署命令(推荐)
May 07 Python
django项目中使用手机号登录的实例代码
Aug 15 Python
Python 中如何实现参数化测试的方法示例
Dec 10 Python
Python各种扩展名区别点整理
Feb 27 Python
Python通过zookeeper实现分布式服务代码解析
Jul 22 Python
Python调用ffmpeg开源视频处理库,批量处理视频
Nov 16 Python
浅析Python实现DFA算法
Jun 26 Python
python多线程方法详解
Jan 18 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
杏林同学录(五)
2006/10/09 PHP
thinkPHP的Html模板标签使用方法
2012/11/13 PHP
php教程之魔术方法的使用示例(php魔术函数)
2014/02/12 PHP
Symfony2学习笔记之插件格式分析
2016/03/17 PHP
Laravel创建数据库表结构的例子
2019/10/09 PHP
JavaScript window.location对象
2014/11/14 Javascript
JavaScript常用的弹出广告及背投广告实现方法
2015/02/06 Javascript
学习javascript的闭包,原型,和匿名函数之旅
2015/10/18 Javascript
学习JavaScript设计模式(继承)
2015/11/26 Javascript
Javascript实现通过选择周数显示开始日和结束日的实现代码
2016/05/30 Javascript
微信小程序 WXDropDownMenu组件详解及实例代码
2016/10/24 Javascript
js实现5秒倒计时重新发送短信功能
2017/02/05 Javascript
Vue.js路由vue-router使用方法详解
2017/03/20 Javascript
vue.js 获取select中的value实例
2018/03/01 Javascript
JS集合set类的实现与使用方法示例
2019/02/01 Javascript
VUE中使用MUI方法
2019/02/12 Javascript
利用Node.js如何实现文件循环覆写
2019/04/05 Javascript
浅谈laytpl 模板空值显示null的解决方法及简单的js表达式
2019/09/19 Javascript
vue 实现路由跳转时更改页面title
2019/11/05 Javascript
Python中针对函数处理的特殊方法
2014/03/06 Python
python实现复制整个目录的方法
2015/05/12 Python
基于Python实现的微信好友数据分析
2018/02/26 Python
对Python中的@classmethod用法详解
2018/04/21 Python
Python BS4库的安装与使用详解
2018/08/08 Python
Python图像处理实现两幅图像合成一幅图像的方法【测试可用】
2019/01/04 Python
python多线程+代理池爬取天天基金网、股票数据过程解析
2019/08/13 Python
Django使用django-simple-captcha做验证码的实现示例
2021/01/07 Python
Python对excel的基本操作方法
2021/02/18 Python
Bootstrap 学习分享
2012/11/12 HTML / CSS
HTML5 canvas画图并保存成图片的jcanvas插件
2014/01/17 HTML / CSS
What's the difference between Debug and Trace class? (Debug类与Trace类有什么区别)
2013/09/10 面试题
园林设计师自荐信
2013/11/18 职场文书
企业党员一句话承诺
2014/05/30 职场文书
导航工程专业自荐信
2014/09/02 职场文书
幼儿园教师求职信
2015/03/20 职场文书
导游词之江南周庄
2019/12/06 职场文书