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 相关文章推荐
windows下wxPython开发环境安装与配置方法
Jun 28 Python
python logging 日志轮转文件不删除问题的解决方法
Aug 02 Python
Python基于pygame模块播放MP3的方法示例
Sep 30 Python
解决python3 安装完Pycurl在import pycurl时报错的问题
Oct 15 Python
Python生成MD5值的两种方法实例分析
Apr 26 Python
Python中@property的理解和使用示例
Jun 11 Python
Python 窗体(tkinter)按钮 位置实例
Jun 13 Python
Python shutil模块用法实例分析
Oct 02 Python
Python子进程subpocess原理及用法解析
Jul 16 Python
Python实现敏感词过滤的4种方法
Sep 12 Python
Python中的特殊方法以及应用详解
Sep 20 Python
python 爬取京东指定商品评论并进行情感分析
May 27 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中防止SQL注入最好的方法是什么
2013/06/10 PHP
php封装好的人民币数值转中文大写类
2015/12/20 PHP
PHP定时执行任务的3种方法详解
2015/12/21 PHP
PHP实现的数独求解问题示例
2017/04/18 PHP
PHP中localeconv()函数的用法
2019/03/26 PHP
在IE下:float属性会影响offsetTop的取值
2006/12/22 Javascript
JavaScript中prototype为对象添加属性的误区介绍
2013/10/15 Javascript
jQuery实现统计输入文字个数的方法
2015/03/11 Javascript
jquery实现手机号码选号的方法
2015/07/31 Javascript
Nodejs抓取html页面内容(推荐)
2016/08/11 NodeJs
jQuery 选择符详细介绍及整理
2016/12/02 Javascript
js实现省份下拉菜单效果
2017/02/15 Javascript
JavaScript中的toString()和toLocaleString()方法的区别
2017/02/15 Javascript
vue2.0中click点击当前li实现动态切换class
2017/06/21 Javascript
JS 中document.write()的用法和清空的原因浅析
2017/12/04 Javascript
浅谈VUE监听窗口变化事件的问题
2018/02/24 Javascript
在Vue项目中,防止页面被缩放和放大示例
2019/10/28 Javascript
vue下canvas裁剪图片实例讲解
2020/04/16 Javascript
Python实现的爬虫功能代码
2017/06/24 Python
Pandas过滤dataframe中包含特定字符串的数据方法
2018/11/07 Python
树莓派用python中的OpenCV输出USB摄像头画面
2019/06/22 Python
200行python代码实现2048游戏
2019/07/17 Python
python实现单目标、多目标、多尺度、自定义特征的KCF跟踪算法(实例代码)
2020/01/08 Python
python tkiner实现 一个小小的图片翻页功能的示例代码
2020/06/24 Python
详解python内置模块urllib
2020/09/09 Python
波兰品牌内衣及泳装网上商店:Astratex.pl
2017/02/03 全球购物
日本著名化妆品零售网站:Cosme Land
2019/03/01 全球购物
房地产管理毕业生自荐信
2013/11/04 职场文书
环保倡议书
2014/04/14 职场文书
商业门面租房协议书
2014/11/25 职场文书
毕业生个人总结
2015/02/28 职场文书
聚众斗殴罪辩护词
2015/05/21 职场文书
新手入门Mysql--概念
2021/06/18 MySQL
国庆节到了,利用JS实现一个生成国庆风头像的小工具 详解实现过程
2021/10/05 Javascript
日本十大血腥动漫,那些被禁播的动漫盘点
2022/03/21 日漫