2

我讨厌在这个标题下提出这个问题,但我实际上不知道发生了什么,所以就这样吧。

我正在做另一个项目,我想在其中使用日志记录模块。代码分布在几个文件中,而不是为单独的文件创建单独的记录器对象,我想创建一个包含内容的 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导入“日志”并打印它们的调试消息。
  3. main.py导入日志,a & b;并打印它自己的调试消息。

文件内容如下:http: //i.imgur.com/XoKVf.png

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

4

3 回答 3

2

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

于 2011-09-27T10:00:55.540 回答
2

为记录器指定一个名称,否则您总是使用根记录器。

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 = logging.getLogger(__name__)

于 2011-09-27T10:01:46.213 回答
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" )
于 2011-09-27T10:01:07.623 回答