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程序
Apr 04 Python
python爬虫入门教程之糗百图片爬虫代码分享
Sep 02 Python
在Python的Flask框架下使用sqlalchemy库的简单教程
Apr 09 Python
Flask框架的学习指南之制作简单blog系统
Nov 20 Python
TensorFlow实现随机训练和批量训练的方法
Apr 28 Python
python爬虫之自动登录与验证码识别
Jun 15 Python
Python关于excel和shp的使用在matplotlib
Jan 03 Python
利用python将图片版PDF转文字版PDF
May 03 Python
使用python实现ftp的文件读写方法
Jul 02 Python
python获取引用对象的个数方式
Dec 20 Python
python输出国际象棋棋盘的实例分享
Nov 26 Python
Python3的进程和线程你了解吗
Mar 16 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编程网上资源导航
2006/10/09 PHP
WordPress主题制作之模板文件的引入方法
2015/12/28 PHP
PHP中Laravel 关联查询返回错误id的解决方法
2017/04/01 PHP
用PHP的反射实现委托模式的讲解
2019/03/22 PHP
使用PHP开发留言板功能
2019/11/19 PHP
sencha touch 模仿tabpanel导航栏TabBar的实例代码
2013/10/24 Javascript
jquery中event对象属性与方法小结
2013/12/18 Javascript
NodeJS Express框架中处理404页面一个方式
2014/05/28 NodeJs
浅谈jquery回调函数callback的使用
2015/01/30 Javascript
jquery中的工具使用方法$.isFunction, $.isArray(), $.isWindow()
2015/08/09 Javascript
浅析BootStrap栅格系统
2016/06/07 Javascript
JS百度地图搜索悬浮窗功能
2017/01/12 Javascript
微信小程序自定义模态对话框实例详解
2017/08/16 Javascript
jQuery实现可兼容IE6的淡入淡出效果告警提示功能示例
2017/09/20 jQuery
Vue.js搭建移动端购物车界面
2020/06/28 Javascript
JavaScript中的一些实用小技巧总结
2019/04/07 Javascript
JS实现简单tab选项卡切换
2019/10/25 Javascript
JavaScript接口实现方法实例分析
2020/05/16 Javascript
js实现简易ATM功能
2020/10/27 Javascript
[51:30]OG vs LGD 2018国际邀请赛淘汰赛BO3 第二场 8.26
2018/08/30 DOTA
详解Python中的循环语句的用法
2015/04/09 Python
python判断windows系统是32位还是64位的方法
2015/05/11 Python
Python自动化开发学习之三级菜单制作
2017/07/14 Python
windows下添加Python环境变量的方法汇总
2018/05/14 Python
如何在python中实现随机选择
2019/11/02 Python
python调用HEG工具批量处理MODIS数据的方法及注意事项
2020/02/18 Python
django 将自带的数据库sqlite3改成mysql实例
2020/07/09 Python
python 用Matplotlib作图中有多个Y轴
2020/11/28 Python
Python爬虫之Selenium警告框(弹窗)处理
2020/12/04 Python
CSS中的字体大小设置属性总结
2016/05/24 HTML / CSS
HTML5的自定义属性data-*详细介绍和JS操作实例
2014/04/10 HTML / CSS
Eagle Eyes Optics鹰眼光学:高性能太阳镜
2018/12/07 全球购物
Laravel的加密解密与哈希实例讲解
2021/03/24 PHP
2016高考寄语集锦
2015/12/04 职场文书
2016优秀员工先进事迹材料
2016/02/25 职场文书
《艾尔登法环》Boss腐烂树灵很有可能是《黑暗之魂3》的一个废案
2022/04/11 其他游戏