Python logging模块异步线程写日志实现过程解析
作者:印第安海盗 发布时间:2023-07-29 05:05:03
标签:python,logging,线程,日志
通过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
文件内容如下:
来源:https://www.cnblogs.com/yindianhaidao/p/13201074.html
0
投稿
猜你喜欢
- 1、我们使用正常的输出语句得到的是(输出结果:division by zero)虽然得到了错误的日志输出,但是不知道为什么出错,也不能定位具
- Insert 和 Update假设现在你要把下面的数据插入到数据库中.ID = 3TheDate=mktime(0,0,0,8,31,200
- 本文实例为大家分享了python绘制直线的具体代码,供大家参考,具体内容如下#!/usr/bin/env pythonimport vtk#
- 一 概述Python生态系统的一些核心基础数据分析库:NumPy:支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库,包含
- 简介这是一篇介绍网页设计原则的文章。在互联网迅速发展的今天,各种web 2.0网站竞争激烈,你死我亡。Jini, D
- 在我做过的N多项目中,基本都有个跑不开的怪圈——首页很难设计。根据进度安排,首页必须按时出来,不然没法review,也没法测试。于是,首页只
- 本文实例讲述了python中as用法。分享给大家供大家参考。具体分析如下:import some # some 为一个模组如果想要改变被导入
- python代码如下:import numpy as np# Write a function that takes as input a
- 利用OpenCV练习读取图片的时候,图片总是一闪而过,不利于观察,这个时候需要利用到waitKey函数。waitKey函数:用来等待按键,当
- pprint的英文全称Data pretty printer,顾名思义就是让显示结果更漂亮。print()和pprint()都是python
- 在这里我们将介绍的是MySQL内存使用上的线程独享,线程独享内存主要用于各客户端连接线程存储各种操作的独享数据,如线程栈信息,分组排序操作,
- 为了获取视频,应该创建一个 VideoCapture 对象。他的参数可以是设备的索引号,或者是一个视频文件。设备索引号就是在指定要使用的摄像
- 近年来,广告已成为很多网站的主要收入来源。不久前,在线广告往往遭到访客的拒绝,广告客户也不确定它的价值和效力。今天,大多数访客期望在商业网站
- 本文从树数据结构说到二叉堆数据结构,再使用二叉堆的有序性对无序数列排序。1. 树树是最基本的数据结构,可以用树映射现实世界中一对多的群体关系
- asp之家注:也许很多人对网页设计中的,id和class和name的区别不是很清楚,好像觉得都可以使用,没什么不同。就我个人来讲,我的理解是
- django的url采用正则表达式进行配置,虽然强大却也广为诟病。反对者们认为django的url配置过于繁琐,且不支持默认的路由功能。我倒
- 前言嗨嗨,大家晚上好 ~ 又来给你们分享小妙招啦在python列表有重复元素时,可以有以下几种方式进行删除觉得不错的话,赶紧学起来用用吧 !
- 一.修改/etc/my.cnf文件default-character-set=utf8[mysqld]datadir= ar b/mysql
- 从Request对象中获取数据我们在第三章讲述View的函数时已经介绍过HttpRequest对象了,但当时并没有讲太多。 让我们回忆下:每
- 在一个网页中,不仅仅只有一个html骨架,还需要css样式文件,js执行文件以及一些图片等。因此在DTL中加载静态文件是一个必须要解决的问题