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 14 Python
Python之web模板应用
Dec 26 Python
numpy 进行数组拼接,分别在行和列上合并的实例
May 08 Python
python并发编程多进程 模拟抢票实现过程
Aug 20 Python
Django 对IP访问频率进行限制的例子
Aug 30 Python
解决pycharm中导入自己写的.py函数出错问题
Feb 12 Python
Python优秀开源项目Rich源码解析的流程分析
Jul 06 Python
Python自动发送和收取邮件的方法
Aug 12 Python
Python如何实现感知器的逻辑电路
Dec 25 Python
python geopandas读取、创建shapefile文件的方法
Jun 29 Python
python turtle绘图命令及案例
Nov 23 Python
http通过StreamingHttpResponse完成连续的数据传输长链接方式
Feb 12 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+FLASH实现上传文件进度条相关文件 下载
2007/07/21 PHP
PHP开发中常用的字符串操作函数
2011/02/08 PHP
PHP取得一个类的属性和方法的实现代码
2011/05/22 PHP
coreseek 搜索英文的问题详解
2013/06/08 PHP
必须收藏的php实用代码片段
2016/02/02 PHP
PHP正则表达式入门教程(推荐)
2016/05/18 PHP
PHP微信企业号开发之回调模式开启与用法示例
2017/11/25 PHP
浅析PHP7 的垃圾回收机制
2019/09/06 PHP
Thinkphp5.0 框架实现控制器向视图view赋值及视图view取值操作示例
2019/10/12 PHP
如何通过Apache在本地配置多个虚拟主机
2020/07/29 PHP
用htc组件制作windows选项卡
2007/01/13 Javascript
JavaScript 页面坐标相关知识整理
2010/01/09 Javascript
jquery实现兼容浏览器的图片上传本地预览功能
2013/10/14 Javascript
详解jquery uploadify 上传文件
2013/11/09 Javascript
JS ES6多行字符串与连接字符串的表示方法
2017/04/26 Javascript
vue+axios+mock.js环境搭建的方法步骤
2018/08/28 Javascript
快速解决vue动态绑定多个class的官方实例语法无效的问题
2018/09/05 Javascript
微信jssdk逻辑在vue中的运用详解
2018/11/14 Javascript
[01:50]《我与DAC》之玩家:iG夺冠时的那面红旗
2018/03/29 DOTA
自己编程中遇到的Python错误和解决方法汇总整理
2015/06/03 Python
举例区分Python中的浅复制与深复制
2015/07/02 Python
Python安装Numpy和matplotlib的方法(推荐)
2017/11/02 Python
使用Python制作微信跳一跳辅助
2018/01/31 Python
浅谈python下含中文字符串正则表达式的编码问题
2018/12/07 Python
基于python纯函数实现井字棋游戏
2020/05/27 Python
python 判断一组数据是否符合正态分布
2020/09/23 Python
python实现按日期归档文件
2021/01/30 Python
Fairyseason:为个人和批发商提供女装和配件
2017/03/01 全球购物
迟到检讨书400字
2014/01/13 职场文书
工商治理实习生的自我评价
2014/01/15 职场文书
优秀少先队大队辅导员事迹材料
2014/05/04 职场文书
安全责任书模板
2014/07/22 职场文书
2015年学校保卫部工作总结
2015/05/11 职场文书
《乌鸦喝水》教学反思
2016/02/19 职场文书
浅谈Golang 切片(slice)扩容机制的原理
2021/06/09 Golang
Python pandas求方差和标准差的方法实例
2021/08/04 Python