导入模块时发生了奇怪的事情

时间:2011-09-27 09:29:30

标签: python python-2.7 python-module

我讨厌在这个问题上提出这个问题,但实际上我不知道发生了什么事情,所以就在这里。

我正在做另一个我想使用日志记录模块的项目。代码分布在少数几个文件中。而不是为单独的文件创建单独的记录器对象,我想到创建一个包含内容的logs.py

import sys, logging

class Logger:
    def __init__(self):
        formatter = logging.Formatter('%(filename)s:%(lineno)s %(levelname)s:%(message)s')
        stdout_handler = logging.StreamHandler(sys.stdout)
        stdout_handler.setFormatter(formatter)
        self.logger=logging.getLogger('')
        self.logger.addHandler(stdout_handler)
        self.logger.setLevel(logging.DEBUG)

    def debug(self, message):
        self.logger.debug(message)

并使用此类(在不同的文件中)。

import logs
b = logs.Logger()
b.debug("Hi from a.py")
  1. 我解决了整个问题,在这里提出问题。现在,我有3个文件,a.py,b.py& main.py.所有3个文件都实例化logs.Logger类并打印调试消息。
  2. a.py& b.py 导入“logs”并打印其调试消息。
  3. main.py 导入日志,a& B'/强>;并打印出自己的调试信息。
  4. 文件内容如下:http://i.imgur.com/XoKVf.png

    为什么来自b.py的调试信息打印2次&来自main.py 3次?

3 个答案:

答案 0 :(得分:2)

每次调用它时,

logging.getLogger('')都会返回完全相同的对象。因此,每次实例化Logger(为什么在这里使用旧式类?)时,您将附加一个处理程序,从而导致打印到另一个目标。由于所有目标指向相同的内容,对.debug()的最后一次调用将打印到指向StreamHandler的三个sys.stdout对象中的每一个,从而导致打印三行。

答案 1 :(得分:2)

指定记录器的名称,否则始终使用root logger。

import sys, logging

class Logger:
    def __init__(self, name):
        formatter = logging.Formatter('%(filename)s:%(lineno)s %(levelname)s:%(message)s')
        stdout_handler = logging.StreamHandler(sys.stdout)
        stdout_handler.setFormatter(formatter)
        self.logger=logging.getLogger(name)
        self.logger.addHandler(stdout_handler)
        self.logger.setLevel(logging.DEBUG)

    def debug(self, message):
        self.logger.debug(message)

http://docs.python.org/howto/logging.html#advanced-logging-tutorial

  

命名记录器时使用的一个好习惯是使用模块级   logger,在每个使用日志记录的模块中,命名如下:

     

logger = logging.getLogger(__name__)

答案 2 :(得分:1)

首先。不要创建自己的Logger类。

只需使用现有的logging配置工具配置现有的记录器类。

二。每次创建自己的Logger类时,您还会创建新的处理程序,然后将新的(重复的)处理程序附加到根记录器。这导致了重复的消息。

如果你有几个模块必须(1)独立运行,(2)也作为更大的复合应用程序的一部分运行,你需要这样做。这将确保只进行一次日志记录配置。

import logging
logger= logging.getLogger( __file__ ) # Unique logger for a, b or main


if __name__ == "__main__":
    logging.basicConfig( stream=sys.stdout, level=logging.DEBUG, format='%(filename)s:%(lineno)s %(levelname)s:%(message)s' )
    # From this point forward, you can use the `logger` object.
    logger.info( "Hi" )