python日志记录确保仅将处理程序添加一次 [英] python logging ensure a handler is added only once

查看:71
本文介绍了python日志记录确保仅将处理程序添加一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段代码正在初始化记录器,如下所示.

I have a piece of code that is initializing a logger as below.

logger = logging.getLogger()
hdlr = logging.FileHandler('logfile.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr) 
logger.setLevel(logging.DEBUG)

不幸的是,此代码被多次调用,有什么方法可以检查处理程序是否已经存在-我宁愿无需使用Singleton来实现它.

Unfortunately this code is being called multiple times, is there any way I can check to see if the handler already exists - I'd prefer to implement this without having to use a Singleton.

对不起,忘了提到这是在python 2.5上-干杯,理查德

Sorry, forgot to mention this is on python 2.5 - cheers, Richard

推荐答案

作为@offbyone注释,可以将冗余处理程序添加到记录器的同一实例. 用于记录日志的python文档 say-

As @offbyone comments, it is possible to add redundant handlers to the same instance of the logger. The python docs for logging say-

多次调用具有相同名称的getLogger()将返回一个 引用相同的记录器对象."

"Multiple calls to getLogger() with the same name will return a reference to the same logger object."

因此,我们不必担心将实现变成单例,

So we don't need to worry about making the implementation a singleton, as it already is.

不幸的是,对于与记录器的相同实例相关联的处理程序,不正确是相同的. 可以附加重复的处理程序.

Unfortunately the same is not true for the handlers associated with the same instance of the logger. There can be duplicate handlers attached.

示例-

  1. 复制此代码并将其保存在main.py

  1. Copy this code and save it in main.py

import logging
print 'inside main.py',
print '-'*50
def logger():

      print 'initializing logger....'
      logPath = '.'
      fileName = 'temp'

      # configure log formatter
      logFormatter = logging.Formatter("%(asctime)s [%(filename)s] [%(funcName)s] [%(levelname)s] [%(lineno)d] %(message)s")

      # configure file handler
      fileHandler = logging.FileHandler("{0}/{1}.log".format(logPath, fileName))
      fileHandler.setFormatter(logFormatter)

      # configure stream handler
      consoleHandler = logging.StreamHandler()
      consoleHandler.setFormatter(logFormatter)

      # get the logger instance
      logger = logging.getLogger(__name__)

      # set the logging level
      logger.setLevel(logging.DEBUG)

      print 'adding handlers- '

      #if not len(logger.handlers):
      logger.addHandler(fileHandler)
      logger.addHandler(consoleHandler)

      print 'logger initialized....\n'
      print 'associated handlers - ', len(logger.handlers)
      for handler in logger.handlers:
            print handler
      print
      return logger

main_logger = logger()
main_logger.info('utilizing main.py logger.')
print 'exiting main.py',
print '-'*50

  • 以及sub.py

  • and the following code in sub.py

    print 'inside sub.py',
    print '-'*50
    print 'importing main.py'
    import main
    print 'imported main.py'
    import logging
    print 'getting logger instance in sub'
    sub_logger = main.logger()
    print 'got logger instance in sub'
    sub_logger.info("utilizing sub_logger")
    print 'exiting sub.py',
    print '-'*50
    

  • 运行sub.py

  • Run sub.py

    narayan@y510p:~/code/so$ python sub.py
    inside sub.py --------------------------------------------------
    importing main.py
    inside main.py --------------------------------------------------
    initializing logger....
    adding handlers- 
    logger initialized....
    
    associated handlers -  2
    <logging.FileHandler object at 0x7f7158740c90>
    <logging.StreamHandler object at 0x7f7158710b10>
    
    2015-08-04 07:41:01,824 [main.py] [<module>] [INFO] [41] utilizing main.py logger.
    exiting main.py --------------------------------------------------
    imported main.py
    getting logger instance in sub
    initializing logger....
    adding handlers- 
    logger initialized....
    
    associated handlers -  4 # <===== 4 handlers (duplicates added)
    <logging.FileHandler object at 0x7f7158740c90>
    <logging.StreamHandler object at 0x7f7158710b10>
    <logging.FileHandler object at 0x7f7158710bd0>
    <logging.StreamHandler object at 0x7f7158710c10>
    
    got logger instance in sub
    2015-08-04 07:41:01,824 [sub.py] [<module>] [INFO] [10] utilizing sub_logger
    2015-08-04 07:41:01,824 [sub.py] [<module>] [INFO] [10] utilizing sub_logger
    exiting sub.py --------------------------------------------------
    

  • 多次调用该方法以返回相同的记录器,从而添加了重复的处理程序.

    Hence multiple calls to the method returning the same logger added duplicate handlers.

    现在,您的问题-

    有什么方法可以检查处理程序是否已经存在

    is there any way I can check to see if the handler already exists

    是的,有-

    logger.handlers返回与给定logger关联的所有处理程序的列表.

    logger.handlers returns a list of all the handlers associated with the given logger.

    在将处理程序添加到记录器实例之前,请确保不要添加重复的处理程序 在main.py中,只需取消注释if not len(logger.handlers):的行并正确缩进以下两行-

    Before adding handlers to an instance of the logger, make sure not to add duplicate handlers In main.py, just un-comment the line that says if not len(logger.handlers): and indent the following two lines properly-

    if not len(logger.handlers):
        logger.addHandler(fileHandler)
        logger.addHandler(consoleHandler)
    

    现在再次运行sub.py

    Now again run sub.py

    narayan@y510p:~/code/so$ python sub.py
    inside sub.py --------------------------------------------------
    importing main.py
    inside main.py --------------------------------------------------
    initializing logger....
    adding handlers- 
    logger initialized....
    
    associated handlers -  2
    <logging.FileHandler object at 0x7fd67a891c90>
    <logging.StreamHandler object at 0x7fd67a862b10>
    
    2015-08-04 08:14:45,620 [main.py] [<module>] [INFO] [41] utilizing main.py logger.
    exiting main.py --------------------------------------------------
    imported main.py
    getting logger instance in sub
    initializing logger....
    adding handlers- 
    logger initialized....
    
    associated handlers -  2 # <===== Still 2 handlers (no duplicates)
    <logging.FileHandler object at 0x7fd67a891c90>
    <logging.StreamHandler object at 0x7fd67a862b10>
    
    got logger instance in sub
    2015-08-04 08:14:45,620 [sub.py] [<module>] [INFO] [10] utilizing sub_logger
    exiting sub.py --------------------------------------------------
    

    此外,如果要限制要添加到记录器实例的处理程序的类型,则可以执行以下操作-

    Further, if you want to limit the type of handlers to be added to the logger instance, you can do something like this-

        print 'adding handlers- '
        # allows to add only one instance of file handler and stream handler
        if len(logger.handlers) > 0:
            print 'making sure we do not add duplicate handlers'
            for handler in logger.handlers:
                  # add the handlers to the logger
                  # makes sure no duplicate handlers are added
    
                  if not isinstance(handler, logging.FileHandler) and not isinstance(handler, logging.StreamHandler):
                        logger.addHandler(fileHandler)
                        print 'added file handler'
                        logger.addHandler(consoleHandler)
                        print 'added stream handler'
        else:
            logger.addHandler(fileHandler)
            logger.addHandler(consoleHandler)
            print 'added handlers for the first time'
    

    希望这会有所帮助!

    不幸的是,对于关联的处理程序,不正确是一样的 与记录器的相同实例. 可以重复 附加的处理程序.

    Unfortunately the same is not true for the handlers associated with the same instance of the logger. There can be duplicate handlers attached.

    事实证明,上述说法并不完全正确.

    It turns out that that above statement is not entirely true.

    假设我们在主模块中创建并配置了一个名为'main_logger'的记录器(仅配置记录器,不返回任何内容).

    Let's suppose we have created and configured a logger called 'main_logger' in the main module (which simply configures the logger, doesn't return anything).

    # get the logger instance
    logger = logging.getLogger("main_logger")
    # configuration follows
    ...
    

    现在在子模块中,如果我们按照命名层次'main_logger.sub_module_logger'创建子记录器,则无需在子模块中对其进行配置.只需按照命名层次创建记录器即可.

    Now in a sub-module, if we create a child logger following the naming hierarchy 'main_logger.sub_module_logger', we don't need to configure it in the sub-module. Just creation of the logger following the naming hierarchy is sufficient.

    # get the logger instance
    logger = logging.getLogger("main_logger.sub_module_logger")
    # no configuration needed
    # it inherits the configuration from the parent logger
    ...
    

    它也不会添加重复的处理程序.

    And it won't add duplicate handler as well.

    参考资料-在多个模块中使用日志记录

    这篇关于python日志记录确保仅将处理程序添加一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆