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 获取本机ip地址的两个方法
Feb 25 Python
理解Python中函数的参数
Apr 27 Python
从零开始学Python第八周:详解网络编程基础(socket)
Dec 14 Python
Python中如何获取类属性的列表
Dec 26 Python
酷! 程序员用Python带你玩转冲顶大会
Jan 17 Python
Python使用OpenCV进行标定
May 08 Python
Python爬虫的两套解析方法和四种爬虫实现过程
Jul 20 Python
Tensorflow 实现修改张量特定元素的值方法
Jul 30 Python
对python3新增的byte类型详解
Dec 04 Python
PyQt5通信机制 信号与槽详解
Aug 07 Python
python+requests接口自动化框架的实现
Aug 31 Python
详解python 支持向量机(SVM)算法
Sep 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
php排序算法(冒泡排序,快速排序)
2012/10/09 PHP
一个简单的PHP验证码实现代码
2014/05/10 PHP
PHP实现git部署的方法教程
2017/12/19 PHP
php菜单/评论数据递归分级算法的实现方法
2019/08/01 PHP
JavaScript面向对象之Prototypes和继承
2012/07/12 Javascript
JS图像无缝滚动脚本非常好用
2014/02/10 Javascript
node.js入门教程
2014/06/01 Javascript
jquery实现将获取的颜色值转换为十六进制形式的方法
2014/12/20 Javascript
JavaScript实现向OL列表内动态添加LI元素的方法
2015/03/21 Javascript
JavaScript实现快速排序的方法
2015/07/31 Javascript
fullpage.js全屏滚动插件使用实例
2016/09/06 Javascript
js正则表达式惰性匹配和贪婪匹配用法分析
2016/12/26 Javascript
codeMirror插件使用讲解
2017/01/16 Javascript
详解javascript常用工具类的封装
2018/01/30 Javascript
jQuery实现基本淡入淡出效果的方法详解
2018/09/05 jQuery
详解如何理解vue的key属性
2019/04/14 Javascript
前端Vue项目详解--初始化及导航栏
2019/06/24 Javascript
简单了解微信小程序的目录结构
2019/07/01 Javascript
ant-design-vue 实现表格内部字段验证功能
2019/12/16 Javascript
小谈angular ng deploy的实现
2020/04/07 Javascript
python调用机器喇叭发出蜂鸣声(Beep)的方法
2015/03/23 Python
用Python编写脚本使IE实现代理上网的教程
2015/04/23 Python
在Python中处理列表之reverse()方法的使用教程
2015/05/21 Python
Python实现打印螺旋矩阵功能的方法
2017/11/21 Python
python3实现跳一跳点击跳跃
2018/01/08 Python
利用python 更新ssh 远程代码 操作远程服务器的实现代码
2018/02/08 Python
春节到了 教你使用python来抢票回家
2020/01/06 Python
解决Tensorflow 使用时cpu编译不支持警告的问题
2020/02/03 Python
在python3中实现更新界面
2020/02/21 Python
解决Pycharm双击图标启动不了的问题(JetBrains全家桶通用)
2020/08/07 Python
美国校园市场:OCM
2017/06/08 全球购物
Rakuten Kobo台湾:电子书、eReaders和Reading应用程式
2017/11/24 全球购物
全球领先的全景影像品牌:Insta360
2019/08/21 全球购物
机电一体化专业应届生求职信
2013/11/27 职场文书
校园网站的创业计划书范文
2013/12/30 职场文书
计划生育证明书写要求
2014/09/17 职场文书