• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    解决python logging遇到的坑 日志重复打印问题

    python 中 logging模块 假如遇到 多线程 或者 多进程 或者在web框架中自定义logging的话(一个请求就是一个独立的线程)非常容易重复打印日志 和造成内存崩溃,所以:

    解决方法如下:

    重写日志方法 用类:

     class Log():
     import logging
     def __init__(self):
     self.logger = logging.getLogger(__name__)
     # 以下三行为清空上次文件
     # 这为清空当前文件的logging 因为logging会包含所有的文件的logging
     logging.Logger.manager.loggerDict.pop(__name__)
     # 将当前文件的handlers 清空 
     self.logger.handlers = []
     # 然后再次移除当前文件logging配置
     self.logger.removeHandler(self.logger.handlers)
     # 这里进行判断,如果logger.handlers列表为空,则添加,否则,直接去写日志
     if not self.logger.handlers:
     # loggger 文件配置路径
     self.handler = logging.FileHandler(os.getcwd() + '/logger/%s_log/%s_score.log' % (str(dt.date.today()), str(dt.date.today())))
     # logger 配置等级
     self.logger.setLevel(logging.DEBUG)
     # logger 输出格式
     formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s')
     # 添加输出格式进入handler
     self.handler.setFormatter(formatter)
     # 添加文件设置金如handler
     self.logger.addHandler(self.handler)
     
     # 以下皆为重写方法 并且每次记录后清除logger
     def info(self,message=None):
     self.__init__()
     self.logger.info(message)
     self.logger.removeHandler(self.logger.handlers)
     
     def debug(self,message=None):
     self.__init__()
     self.logger.debug(message)
     self.logger.removeHandler(self.logger.handlers)
     
     def warning(self,message=None):
     self.__init__()
     self.logger.warning(message)
     self.logger.removeHandler(self.logger.handlers)
     
     def error(self,message=None):
     self.__init__()
     self.logger.error(message)
     self.logger.removeHandler(self.logger.handlers)
     
     def critical(self, message=None):
     self.__init__()
     self.logger.critical(message)
     self.logger.removeHandler(self.logger.handlers)
    

    亲测有效!

    另外 模块尤其注意 例如web请求的时候 在接口处调用 然后引导传参 千万别做全局变量

    补充:python中多个文件共用logger,重复打印问题的解决方案

    问题背景现象

    最近在项目中,需要用python的logging库来将日志打印到文件中,然后将python脚本放到crontab中执行。所以写了一个logger的简单封装。

    如下:

    #!/usr/bin/python
    # -*- coding:utf-8 -*- 
    import logging
    import time
    import os 
    class Log(object):
     '''
    封装后的logging
     ''' 
     def __init__(self, logger=None, log_cate='search'):
      '''
       指定保存日志的文件路径,日志级别,以及调用文件
       将日志存入到指定的文件中
      ''' 
      # 创建一个logger
      self.logger = logging.getLogger(logger)
      self.logger.setLevel(logging.DEBUG)
      # 创建一个handler,用于写入日志文件
      self.log_time = time.strftime("%Y_%m_%d")
      file_dir = os.getcwd() + '/../log'
      if not os.path.exists(file_dir):
       os.mkdir(file_dir)
      self.log_path = file_dir
      self.log_name = self.log_path + "/" + log_cate + "." + self.log_time + '.log'
      # print(self.log_name)
     
      fh = logging.FileHandler(self.log_name, 'a') # 追加模式 这个是python2的
      # fh = logging.FileHandler(self.log_name, 'a', encoding='utf-8') # 这个是python3的
      fh.setLevel(logging.INFO)
     
      # 再创建一个handler,用于输出到控制台
      ch = logging.StreamHandler()
      ch.setLevel(logging.INFO)
     
      # 定义handler的输出格式
      formatter = logging.Formatter(
       '[%(asctime)s] %(filename)s->%(funcName)s line:%(lineno)d [%(levelname)s]%(message)s')
      fh.setFormatter(formatter)
      ch.setFormatter(formatter)
     
      # 给logger添加handler
      self.logger.addHandler(fh)
      self.logger.addHandler(ch)
     
      # 添加下面一句,在记录日志之后移除句柄
      # self.logger.removeHandler(ch)
      # self.logger.removeHandler(fh)
      # 关闭打开的文件
      fh.close()
      ch.close()
     
     def getlog(self):
      return self.logger

    目的是让所有用到logger的地方,只import这个封装库就行,然后直接调用。比如调用logger的

    a.py

    #!/usr/bin/python
    # -*- coding:utf-8 -*-
     
    from common.log import Log
    log = Log().getlog()
    log.info("I am a.py")

    b.py

    #!/usr/bin/python
    # -*- coding:utf-8 -*-
     
    from common.log import Log
    log = Log().getlog()
    log.info("I am b.py")

    c.py

    #!/usr/bin/python
    # -*- coding:utf-8 -*-
     
    import a
    import b
    from common.log import Log 
    log = Log().getlog()
    log.info("I am c.py")

    此时执行c.py的结果如下:

    ➜ search git:(master) ✗ python c.py

    [2019-01-14 15:58:35,807] a.py->module> line:6 [INFO]I am a.py

    [2019-01-14 15:58:35,808] b.py->module> line:6 [INFO]I am b.py

    [2019-01-14 15:58:35,808] b.py->module> line:6 [INFO]I am b.py

    [2019-01-14 15:58:35,809] c.py->module> line:8 [INFO]I am c.py

    [2019-01-14 15:58:35,809] c.py->module> line:8 [INFO]I am c.py

    [2019-01-14 15:58:35,809] c.py->module> line:8 [INFO]I am c.py

    可见,a.py, b.py,c.py的logger共用了,出现了重复打印。

    问题原因分析

    从现象可以得出,不同文件间的log系统是相互影响的,在a.py,b.py, c.py中,我们的调用方式是log = Log().getlog(), 即self.logger = logging.getLogger(logger),logger参数并未传递 , 所以得到的self.logger是RootLogger。

    RootLogger是一个python程序内全局唯一的,所有Logger对象的祖先。所以我们对RootLogger的设定,自然会影响到所有的日志输出。简言之,就是先打开的文件中对log的设置,后打开的文件都会受到影响,都会走一遍logger的继承关系。在这个示例中,b.py在a.py之后被import, 所以b.py会执行一次自己的logger,再执行一次a.py中打开的RootLogger, 以此类推.........

    问题解决方式

    不用默认的RootLogger, 给每个Logger都加个名字。

    a.py

    from common.log import Log
    log = Log(__name__).getlog()
    log.info("I am a.py")

    b.py

    from common.log import Log
    log = Log(__name__).getlog()
    log.info("I am b.py")

    c.py

    import b
    import a 
    from common.log import Log 
    log = Log(__name__).getlog()
    log.info("I am c.py")

    c.py的最新执行结果:

    ➜ search git:(master) ✗ python c.py

    [2019-01-14 16:24:12,008] b.py->module> line:6 [INFO]I am b.py

    [2019-01-14 16:24:12,009] a.py->module> line:6 [INFO]I am a.py

    [2019-01-14 16:24:12,009] c.py->module> line:10 [INFO]I am c.py

    没有重复了,符合预期。问题得以解决。

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

    您可能感兴趣的文章:
    • python 实现logging动态变更输出日志文件名
    • python (logging) 日志按日期、大小回滚的操作
    • Python日志打印里logging.getLogger源码分析详解
    • python 如何对logging日志封装
    • Python logging自定义字段输出及打印颜色
    • Python中logging日志的四个等级和使用
    • Python+logging输出到屏幕将log日志写入文件
    • Python logging模块handlers用法详解
    • 如何理解python接口自动化之logging日志模块
    上一篇:Python 的lru_cache装饰器使用简介
    下一篇:python 基于Appium控制多设备并行执行
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    解决python logging遇到的坑 日志重复打印问题 解决,python,logging,遇到,的,