我讨厌在这个问题上提出这个问题,但实际上我不知道发生了什么事情,所以就在这里。
我正在做另一个我想使用日志记录模块的项目。代码分布在少数几个文件中。而不是为单独的文件创建单独的记录器对象,我想到创建一个包含内容的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")
文件内容如下:http://i.imgur.com/XoKVf.png
为什么来自b.py的调试信息打印2次&来自main.py 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" )