简体   繁体   English

Python记录器忽略类中的FileHandler和StreamHandler级别

[英]Python logger ignores FileHandler and StreamHandler levels in class

I am trying to set a different logger level for my log files and stream, and I have (seemingly) followed the demo ( https://docs.python.org/3/howto/logging-cookbook.html ) to the dot. 我正在尝试为日志文件和流设置不同的记录器级别,并且(似乎)已将演示( https://docs.python.org/3/howto/logging-cookbook.html )跟踪到了点。 However, in my actual code it does not work. 但是,在我的实际代码中,它不起作用。 Running this demo bare in a test script works: 只需在测试脚本中运行此演示即可:

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)

results in 结果是

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

But this for some reason will not execute properly in the actual code: 但这由于某种原因将无法在实际代码中正确执行:

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

Any invocations to self.logger output both to the console and the logfile at the logging.DEBUG level -- which is obviously not what I want. self.logger的任何调用都将输出到控制台和logging.DEBUG级别的日志文件,这显然不是我想要的。 I am very confused as to what I am missing since when I ask the main method what its filehandlers are I get 我对丢失的内容感到非常困惑,因为当我问主要方法时,我得到了它的文件处理程序是什么

print(self.logger.handlers)
print(self.logger)
[<StreamHandler <stderr> (ERROR)>, <FileHandler /home/Projects/claritydb/do_stuff.log (DEBUG)>]
<Logger do_stuff (DEBUG)>

Which is identical to the test case, but there are all the info level outputs in both my console and log file. 这与测试用例相同,但是在控制台和日志文件中都有所有信息级别的输出。 Changing my handler.setLevel commands has no effect on the output, the only thing that changes it is the change of the setLevel command to the initial logger call at the very top of the definitions (ie ch.setLevel and fh.setLevel have no effect, but logger.setLevel does [And I think it is only supposed to be the initial filter). 更改我的handler.setLevel命令对输出没有影响,唯一改变的是将setLevel命令更改为定义顶部的初始记录器调用(即ch.setLevel和fh.setLevel不起作用) ,但logger.setLevel确实存在[而且我认为它应该只是初始过滤器)。

This is driving me nuts, does anyone have any idea? 这真让我发疯,有人知道吗?

EDIT1: Changing the EDIT1:更改

logger = logging.getLogger(f"do_stuff")

line to 线到

logger = logging.getLogger()

seems to solve the problem, but I have no idea why... 似乎可以解决问题,但我不知道为什么...

When you call logger = logging.getLogger() you are getting the root logger and afterwards append your handlers and set its level and so on. 当您调用logger = logging.getLogger()您将获得根记录器,然后追加处理程序并设置其级别,依此类推。 When you do logger = logging.getLogger(f"do_stuff") you are getting a logger called do_stuff but the root logger still exists and your newly created logger propagates it's logs to the root loggers handlers. 当您执行logger = logging.getLogger(f"do_stuff")您会得到一个名为do_stuff的记录器,但根记录器仍然存在,并且新创建的记录器会将其日志传播到根记录器处理程序。 Since in that scenario the root logger has no handlers added to it, it uses the default logging.lastResort with it's default level. 因为在那种情况下,根记录器没有添加任何处理程序,所以它使用默认的logging.lastResort及其默认级别。 You can fix this in a number of ways. 您可以通过多种方式解决此问题。 One easy solution is to set logger.propagate = False . 一种简单的解决方案是设置logger.propagate = False

You also don't need this fh.setLevel(getattr(logging, verbosity_log)) . 您也不需要此fh.setLevel(getattr(logging, verbosity_log)) Python handles the strings passed in directly just fine. Python可以直接处理传入的字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM