如何解决python日志记录确保仅添加一次处理程序
| 我有一段代码正在初始化记录器,如下所示。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的情况下实现该代码。
编辑:对不起,忘了提到这是在python 2.5上-干杯,理查德
解决方法
作为@offbyone注释,可以将冗余处理程序添加到记录器的同一实例。
用于记录的python文档说-
\“多次调用具有相同名称的getLogger()将返回一个
引用相同的记录器对象。\“
因此,我们不必担心将实现变成单一实例。
不幸的是,对于与记录器的相同实例相关联的处理程序,情况并非如此。可以附加重复的处理程序。
例-
复制此代码并将其保存在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中的以下代码
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
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 --------------------------------------------------
因此,对返回相同记录器的方法的多次调用增加了重复的处理程序。
现在,对于您的问题-
有什么办法可以检查处理程序是否已经存在
就在这里-
logger.handlers
返回与给定的logger
相关的所有处理程序的列表。
在将处理程序添加到记录器实例之前,请确保不要添加重复的处理程序
在main.py中,只需取消注释表示if not len(logger.handlers):
的行,并正确缩进以下两行,
if not len(logger.handlers):
logger.addHandler(fileHandler)
logger.addHandler(consoleHandler)
现在再次运行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 --------------------------------------------------
此外,如果您想限制要添加到logger实例中的处理程序的类型,则可以执行以下操作:
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\'
希望这可以帮助!
编辑:
不幸的是,对于关联的处理程序,情况并非如此
与记录器的相同实例。可以重复
附加的处理程序。
事实证明,上述说法并不完全正确。
假设我们已经在主模块中创建并配置了一个名为\'main_logger \'的记录器(仅配置记录器,不返回任何内容)。
# get the logger instance
logger = logging.getLogger(\"main_logger\")
# configuration follows
...
现在在子模块中,如果我们按照命名层次\'main_logger.sub_module_logger \'创建子记录器,则无需在子模块中对其进行配置。只需按照命名层次创建记录器就足够了。
# get the logger instance
logger = logging.getLogger(\"main_logger.sub_module_logger\")
# no configuration needed
# it inherits the configuration from the parent logger
...
而且它也不会添加重复的处理程序。
参考-在多个模块中使用日志记录
, 那么logger.addHandler()将不会添加处理程序(如果该处理程序已存在)。要检查处理程序是否已经存在,可以查看logger.handlers列表:
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)
print logger.handlers
# [<logging.FileHandler object at 0x14542d0>]
logger.addHandler(hdlr)
print logger.handlers
# [<logging.FileHandler object at 0x14542d0>]
此外,如果您有一个或包的__init__.py
文件,我建议您将此代码放在main()函数中,这样就不必每次都调用它。我还将建议您使用命名记录器,而不要使用根记录器。像这样:
logger = logging.getLogger(__name__)
...
希望这对您有所帮助:)
, 您也可以只检查处理程序列表是否为空。这是我想到的解决方案:
def setup_logging(self,logfile):
self._logger = logging.getLogger(\'TestSuite\')
self._logger.setLevel(logging.INFO)
host = socket.gethostname().split(\'.\')[0]
if self._logger.handlers == []:
fh = logging.handlers.RotatingFileHandler(logfile,maxBytes=10*1024*1024,backupCount=5)
strfmt = \"%\" + \"(asctime)s [%s] \" % host + \"%\" + \"(message)s\"
fmt = logging.Formatter(strfmt,datefmt=\"%Y.%m%d %H:%M:%S\")
fh.setFormatter(fmt)
self._logger.addHandler(fh)
self._logger.info(\'-\' * (55 - len(host)))
我看到处理程序已添加多次,因此每个日志消息都多次写入到日志文件中,并且此问题已得到修复。
, 尝试检查ѭ5是否已设定。例如,如果此代码在函数内部:
logger = None
def init_logger():
global logger
if logger is not None:
#logger has already been initialized
return
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)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。