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实现获取命令行输出结果的方法
Jun 10 Python
详解Tensorflow数据读取有三种方式(next_batch)
Feb 01 Python
详解python之协程gevent模块
Jun 14 Python
Python 字符串与数字输出方法
Jul 16 Python
详解Python下载图片并保存本地的两种方式
May 15 Python
Python queue队列原理与应用案例分析
Sep 27 Python
python爬虫库scrapy简单使用实例详解
Feb 10 Python
Python实现链表反转的方法分析【迭代法与递归法】
Feb 22 Python
基于Keras的格式化输出Loss实现方式
Jun 17 Python
一篇文章搞懂python的转义字符及用法
Sep 03 Python
如何利用Matlab制作一款真正的拼图小游戏
May 11 Python
PyTorch中permute的使用方法
Apr 26 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/06/07 PHP
PHP调试的强悍利器之PHPDBG
2016/02/22 PHP
PHP中OpenSSL加密问题整理
2017/12/14 PHP
用Javascript评估用户输入密码的强度实现代码
2011/11/30 Javascript
jQuery UI Autocomplete 1.8.16 中文输入修正代码
2012/04/16 Javascript
浅析JavaScript中两种类型的全局对象/函数
2013/12/05 Javascript
jquery 操作两个select实现值之间的互相传递
2014/03/07 Javascript
ANGULARJS中用NG-BIND指令实现单向绑定的例子
2014/12/08 Javascript
javascript闭包概念简单解析(推荐)
2016/06/03 Javascript
JavaScript仿网易选项卡制作代码
2016/10/06 Javascript
Sortable.js拖拽排序使用方法解析
2016/11/04 Javascript
canvas学习之API整理笔记(一)
2016/12/29 Javascript
使用jQuery实现动态添加小广告
2017/07/11 jQuery
详解ES6中的代理模式——Proxy
2018/01/08 Javascript
使用Angular-CLI构建NPM包的方法
2018/09/07 Javascript
微信小程序如何引用外部js,外部样式,公共页面模板
2019/07/23 Javascript
vue 父组件通过v-model接收子组件的值的代码
2019/10/27 Javascript
详解JavaScript中new操作符的解析和实现
2020/09/04 Javascript
vue v-on:click传递动态参数的步骤
2020/09/11 Javascript
[50:21]Liquid vs Winstrike 2018国际邀请赛小组赛BO2 第二场
2018/08/19 DOTA
python从入门到精通(DAY 3)
2015/12/20 Python
Python面向对象编程之继承与多态详解
2018/01/16 Python
解决django同步数据库的时候app models表没有成功创建的问题
2019/08/09 Python
python实现超市管理系统(后台管理)
2019/10/25 Python
python GUI库图形界面开发之PyQt5窗口控件QWidget详细使用方法
2020/02/26 Python
Python内建序列通用操作6种实现方法
2020/03/26 Python
python 日志 logging模块详细解析
2020/03/31 Python
python爬虫破解字体加密案例详解
2021/03/02 Python
阿波罗盒子:Apollo Box
2017/08/14 全球购物
Hertz荷兰:荷兰和全球租车
2018/01/07 全球购物
python3美化表格数据输出结果的实现代码
2021/04/14 Python
python中的class_static的@classmethod的巧妙用法
2021/06/22 Python
MySQL如何解决幻读问题
2021/08/07 MySQL
用JS创建一个录屏功能
2021/11/11 Javascript
WINDOWS 64位 下安装配置mysql8.0.25最详细的教程
2022/03/22 MySQL
python和C/C++混合编程之使用ctypes调用 C/C++的dll
2022/04/29 Python