zoukankan      html  css  js  c++  java
  • Python logging模块异步线程写日志实现过程解析

    通过logging模块,重写一个logging2模块,独立开启线程,将待写的日志信息异步放入队列,做到日志输出不影响主流程性能,环境python3.8
    logging2.py
    importos
    importthreading
    importqueue
    importtime
    importdatetime
    importlogging
    fromlogging.handlers importRotatingFileHandler
     
    classlogging2(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)
     
    iflogLevel =='DEBUG':
    self.logger.setLevel(level =logging.DEBUG)
    self.rHandler.setLevel(logging.DEBUG)
    self.console.setLevel(logging.DEBUG)
    eliflogLevel =='INFO':
    self.logger.setLevel(level =logging.INFO)
    self.rHandler.setLevel(logging.INFO)
    self.console.setLevel(logging.INFO)
    eliflogLevel =='WARNING':
    self.logger.setLevel(level =logging.WARN)
    self.rHandler.setLevel(logging.WARN)
    self.console.setLevel(logging.WARN)
    eliflogLevel =='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)
     
    #如果跨天了,则重新生成新的文件名
    defreSetLog(self):
    AdtTemp =datetime.datetime.now().strftime('%Y%m%d')
    #比较新的时间
    ifAdtTemp ==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
     
    defrun(self):
    print("开启日志线程:"+self.name)
    i =0
    whileTrue:
    #data = "queue test data"
    #debug(data)
    #print("Queuesize: %s" % (logging2.AQueue.qsize()))
    self.reSetLog()
    iflogging2.AQueue.empty() ==False:
    #从队列获取日志消息
    data =logging2.AQueue.get()
    #解析日志消息,格式:日志级别,内容
    level =list(data.keys())[0]
    content =data.get(level)
    #把内容按分隔符|解析成list传入参数
    lstContent =list(content.split('|'))
    iflevel =='DEBUG':
    self.logger.debug(*lstContent)
    eliflevel =='INFO':
    self.logger.info(*lstContent)
    eliflevel =='WARNING':
    self.logger.warn(*lstContent)
    eliflevel =='ERROR':
    self.logger.error(*lstContent)
    else:
    time.sleep(0.5)
     
    print("退出线程:"+self.name)
     
    defdebug(*content):
    logMsg =""
    #传入多个参数用竖线分隔符分开
    fori inrange(len(content)):
    ifi ==len(content)-1:
    logMsg +=content[i]
    else:
    logMsg +=content[i]+"|"
    logging2.AQueue.put({'DEBUG':logMsg})
     
    definfo(*content):
    logMsg =""
    fori inrange(len(content)):
    ifi ==len(content)-1:
    logMsg +=content[i]
    else:
    logMsg +=content[i]+"|"
    logging2.AQueue.put({'INFO':logMsg})
     
    defwarn(*content):
    logMsg =""
    fori inrange(len(content)):
    ifi ==len(content)-1:
    logMsg +=content[i]
    else:
    logMsg +=content[i]+"|"
    logging2.AQueue.put({'WARNING':logMsg})
     
    deferror(*content):
    logMsg =""
    fori inrange(len(content)):
    ifi ==len(content)-1:
    logMsg +=content[i]
    else:
    logMsg +=content[i]+"|"
    logging2.AQueue.put({'ERROR':logMsg})
     
    definit(module, level):
    # 创建新线程
    thread1 =logging2(1, "Thread-log", module, level)
    # 开启新线程
    thread1.start()
    # thread1.join()
    测试桩logMain.py
    importsys
    importos
    importtime
    importthreading
     
    if__name__ =='__main__':
    importlogging2
    logging2.init("logMain", "DEBUG")
     
    teststr ="22222"
     
    whileTrue:
    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
    文件内容如下:
     
     
    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
  • 相关阅读:
    three.js cannon.js物理引擎之齿轮动画
    three.js cannon.js物理引擎之约束(二)
    three.js cannon.js物理引擎制作一个保龄球游戏
    three.js cannon.js物理引擎之制作拥有物理特性的汽车
    three.js cannon.js物理引擎之Heightfield
    three.js cannon.js物理引擎地形生成器和使用指针锁定控件
    three.js 之cannon.js物理引擎
    设计模式概述
    设计模式之单例模式
    java设计模式之抽象工厂
  • 原文地址:https://www.cnblogs.com/nanhe/p/13508889.html
Copyright © 2011-2022 走看看