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实现的一个p2p文件传输实例
Jun 04 Python
python实现上传样本到virustotal并查询扫描信息的方法
Oct 05 Python
Python实现子类调用父类的方法
Nov 10 Python
Python单例模式实例分析
Jan 14 Python
python实现的简单猜数字游戏
Apr 04 Python
Python实现的远程登录windows系统功能示例
Jun 21 Python
python获取全国城市pm2.5、臭氧等空气质量过程解析
Oct 12 Python
Scrapy框架实现的登录网站操作示例
Feb 06 Python
浅析matlab中imadjust函数
Feb 27 Python
Python实现列表中非负数保留,负数转化为指定的数值方式
Jun 04 Python
利用Python发送邮件或发带附件的邮件
Nov 12 Python
教你如何使用Python下载B站视频的详细教程
Apr 29 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实现采集程序原理和简单示例代码
2007/03/18 PHP
php curl基本操作详解
2013/07/23 PHP
PHP输出一个等腰三角形的方法
2015/05/12 PHP
php字符集转换
2017/01/23 PHP
php连接MSsql server的五种方法总结
2018/03/04 PHP
JavaScript 学习笔记(九)call和apply方法
2010/01/11 Javascript
javascript 学习笔记(八)javascript对象
2011/04/12 Javascript
原生js拖拽(第一课 未兼容)拖拽思路
2013/03/29 Javascript
js实现俄罗斯方块小游戏分享
2014/01/31 Javascript
JavaScript中使用ActiveXObject操作本地文件夹的方法
2014/03/28 Javascript
javascript Deferred和递归次数限制实例
2014/10/21 Javascript
js控制输入框获得和失去焦点时状态显示的方法
2015/01/30 Javascript
分享JavaScript监听全部Ajax请求事件的方法
2016/08/28 Javascript
js按条件生成随机json:randomjson实现方法
2017/04/07 Javascript
JS路由跳转的简单实现代码
2017/09/21 Javascript
Vue写一个简单的倒计时按钮功能
2018/04/20 Javascript
在 Vue 项目中引入 tinymce 富文本编辑器的完整代码
2018/05/04 Javascript
JS中的算法与数据结构之常见排序(Sort)算法详解
2019/08/16 Javascript
js实现前端界面导航栏下拉列表
2020/08/27 Javascript
Ant design vue table 单击行选中 勾选checkbox教程
2020/10/24 Javascript
原生JS实现拖拽效果
2020/12/04 Javascript
python简单判断序列是否为空的方法
2015/06/30 Python
Python面向对象程序设计类的封装与继承用法示例
2019/04/12 Python
python实现关闭第三方窗口的方法
2019/06/28 Python
python tornado修改log输出方式
2019/11/18 Python
Python的几种主动结束程序方式
2019/11/22 Python
PyCharm 2020 激活到 2100 年的教程
2020/03/25 Python
将HTML5 Canvas的内容保存为图片借助toDataURL实现
2013/05/20 HTML / CSS
巴西香水和化妆品购物网站:The Beauty Box
2019/09/03 全球购物
硕士研究生自我鉴定
2013/11/08 职场文书
中学教师请假制度
2014/02/03 职场文书
十八大演讲稿
2014/05/22 职场文书
社区科普工作方案
2014/06/03 职场文书
2014年党员整改措施
2014/10/24 职场文书
2016年5月份红领巾广播稿
2015/12/21 职场文书
Java面试题冲刺第十七天--基础篇3
2021/08/07 面试题