Python 记录器忽略 class 中的 FileHandler 和 StreamHandler 级别
Python logger ignores FileHandler and StreamHandler levels in class
我正在尝试为我的日志文件和流设置不同的记录器级别,并且我(表面上)已经完全按照演示 (https://docs.python.org/3/howto/logging-cookbook.html) 进行了操作。但是,在我的实际代码中它不起作用。 运行 此演示仅在测试脚本中有效:
import logging
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)
# create file handler which logs even debug messages
fh = logging.FileHandler('spam.log')
fh.setLevel(logging.DEBUG)
# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
fh.setFormatter(formatter)
# add the handlers to logger
logger.addHandler(ch)
logger.addHandler(fh)
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')
print(logger.handlers)
print(logger)
结果
alex@alexpc:~/Projects/claritydb$ python test.py ; cat spam.log
2019-09-16 11:53:44,293 - simple_example - ERROR - error message
2019-09-16 11:53:44,293 - simple_example - CRITICAL - critical message
[<StreamHandler <stderr> (ERROR)>, <FileHandler /home/Projects/claritydb/spam.log (DEBUG)>]
<Logger simple_example (DEBUG)>
2019-09-16 11:53:44,293 - simple_example - DEBUG - debug message
2019-09-16 11:53:44,293 - simple_example - INFO - info message
2019-09-16 11:53:44,293 - simple_example - WARNING - warn message
2019-09-16 11:53:44,293 - simple_example - ERROR - error message
2019-09-16 11:53:44,293 - simple_example - CRITICAL - critical message
但由于某些原因,在实际代码中无法正确执行:
class MyClass(object):
def __init__(self,
verbosity_stream="WARNING",
verbosity_log="INFO"):
self.logger = self.setup_logger(verbosity_stream=verbosity_stream, verbosity_log=verbosity_log)
def setup_logger(self, verbosity_stream="ERROR", verbosity_log="WARNING"):
# Create a custom logger
logger = logging.getLogger(f"do_stuff")
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler(f"do_stuff.log", mode='w')
fh.setLevel(getattr(logging, verbosity_log))
ch = logging.StreamHandler()
ch.setLevel(getattr(logging, verbosity_stream))
# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
fh.setFormatter(formatter)
# add the handlers to the self.logger
logger.addHandler(ch)
logger.addHandler(fh)
print(logger.handlers)
return logger
对 self.logger 的任何调用都会在 logging.DEBUG 级别输出到控制台和日志文件——这显然不是我想要的。我对我遗漏的内容感到非常困惑,因为当我询问主要方法时,我得到了它的文件处理程序
print(self.logger.handlers)
print(self.logger)
[<StreamHandler <stderr> (ERROR)>, <FileHandler /home/Projects/claritydb/do_stuff.log (DEBUG)>]
<Logger do_stuff (DEBUG)>
这与测试用例相同,但我的控制台和日志文件中都有所有信息级别的输出。更改我的 handler.setLevel 命令对输出没有影响,唯一改变它的是将 setLevel 命令更改为定义最顶部的初始记录器调用(即 ch.setLevel 和 fh.setLevel 没有效果,但是 logger.setLevel 有效果 [而且我认为它应该只是初始过滤器]。
这让我抓狂,有人知道吗?
EDIT1:更改
logger = logging.getLogger(f"do_stuff")
行到
logger = logging.getLogger()
似乎解决了问题,但我不知道为什么...
当您调用 logger = logging.getLogger()
时,您将获得根记录器,然后附加您的处理程序并设置其级别等。当您执行 logger = logging.getLogger(f"do_stuff")
时,您会得到一个名为 do_stuff
的记录器,但根记录器仍然存在,并且您新创建的记录器将其日志传播到根记录器处理程序。因为在那种情况下,根记录器没有添加任何处理程序,所以它使用默认的 logging.lastResort
及其默认级别。您可以通过多种方式解决此问题。一种简单的解决方案是设置 logger.propagate = False
.
你也不需要这个fh.setLevel(getattr(logging, verbosity_log))
。 Python 直接处理传入的字符串就好了。
我正在尝试为我的日志文件和流设置不同的记录器级别,并且我(表面上)已经完全按照演示 (https://docs.python.org/3/howto/logging-cookbook.html) 进行了操作。但是,在我的实际代码中它不起作用。 运行 此演示仅在测试脚本中有效:
import logging
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)
# create file handler which logs even debug messages
fh = logging.FileHandler('spam.log')
fh.setLevel(logging.DEBUG)
# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
fh.setFormatter(formatter)
# add the handlers to logger
logger.addHandler(ch)
logger.addHandler(fh)
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')
print(logger.handlers)
print(logger)
结果
alex@alexpc:~/Projects/claritydb$ python test.py ; cat spam.log
2019-09-16 11:53:44,293 - simple_example - ERROR - error message
2019-09-16 11:53:44,293 - simple_example - CRITICAL - critical message
[<StreamHandler <stderr> (ERROR)>, <FileHandler /home/Projects/claritydb/spam.log (DEBUG)>]
<Logger simple_example (DEBUG)>
2019-09-16 11:53:44,293 - simple_example - DEBUG - debug message
2019-09-16 11:53:44,293 - simple_example - INFO - info message
2019-09-16 11:53:44,293 - simple_example - WARNING - warn message
2019-09-16 11:53:44,293 - simple_example - ERROR - error message
2019-09-16 11:53:44,293 - simple_example - CRITICAL - critical message
但由于某些原因,在实际代码中无法正确执行:
class MyClass(object):
def __init__(self,
verbosity_stream="WARNING",
verbosity_log="INFO"):
self.logger = self.setup_logger(verbosity_stream=verbosity_stream, verbosity_log=verbosity_log)
def setup_logger(self, verbosity_stream="ERROR", verbosity_log="WARNING"):
# Create a custom logger
logger = logging.getLogger(f"do_stuff")
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler(f"do_stuff.log", mode='w')
fh.setLevel(getattr(logging, verbosity_log))
ch = logging.StreamHandler()
ch.setLevel(getattr(logging, verbosity_stream))
# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
fh.setFormatter(formatter)
# add the handlers to the self.logger
logger.addHandler(ch)
logger.addHandler(fh)
print(logger.handlers)
return logger
对 self.logger 的任何调用都会在 logging.DEBUG 级别输出到控制台和日志文件——这显然不是我想要的。我对我遗漏的内容感到非常困惑,因为当我询问主要方法时,我得到了它的文件处理程序
print(self.logger.handlers)
print(self.logger)
[<StreamHandler <stderr> (ERROR)>, <FileHandler /home/Projects/claritydb/do_stuff.log (DEBUG)>]
<Logger do_stuff (DEBUG)>
这与测试用例相同,但我的控制台和日志文件中都有所有信息级别的输出。更改我的 handler.setLevel 命令对输出没有影响,唯一改变它的是将 setLevel 命令更改为定义最顶部的初始记录器调用(即 ch.setLevel 和 fh.setLevel 没有效果,但是 logger.setLevel 有效果 [而且我认为它应该只是初始过滤器]。
这让我抓狂,有人知道吗?
EDIT1:更改
logger = logging.getLogger(f"do_stuff")
行到
logger = logging.getLogger()
似乎解决了问题,但我不知道为什么...
当您调用 logger = logging.getLogger()
时,您将获得根记录器,然后附加您的处理程序并设置其级别等。当您执行 logger = logging.getLogger(f"do_stuff")
时,您会得到一个名为 do_stuff
的记录器,但根记录器仍然存在,并且您新创建的记录器将其日志传播到根记录器处理程序。因为在那种情况下,根记录器没有添加任何处理程序,所以它使用默认的 logging.lastResort
及其默认级别。您可以通过多种方式解决此问题。一种简单的解决方案是设置 logger.propagate = False
.
你也不需要这个fh.setLevel(getattr(logging, verbosity_log))
。 Python 直接处理传入的字符串就好了。