默认情况下,python logger级别从root设置继承为警告

时间:2017-06-27 14:55:19

标签: python logging log-level

在我的程序中,我在开头定义了一个类似于此的记录器:

BUILD file looks like this:

package(default_visibility = ["//visibility:public"])

java_library(
    name = "X-thrift-s",
    srcs = glob(["*.java"]),
    deps = [
        "//thrift/services/X:XService",
    "//java/com/.../services/X/service:thrift-server",
    ]
)

java_import(
    name = "X-thrift-p",
    jars = [
        "//external:thrift-jar",
        "//external:opencsv-jar",
        "//java/lib:cspj-jar",
    ]
)

load("//tools/bzl:genthrift.bzl","thrift_java_library")

thrift_java_library(
 name = "XService",
 srcs = [
     "XService.thrift"        
 ],
)


java_binary(
   name = "XHandler-Test",
   srcs = glob(["*.java"]),
   main_class = "com.......service.tests.XHandlerTest",
   deps = [
       "//java/....:X-thrift",
       "//java/com.....:thrift-server",
       "//java/com.....:XService",
   ],  
)

然后我有多个从我的主程序调用的文件。为了使它们正常工作,我需要执行以下操作:

def start_logger():
        fh = logging.handlers.RotatingFileHandler('logger.log', 
                                                  maxBytes=1000000, 
                                                  backupCount=100)
        fh.setLevel(logging.DEBUG)

        ch = logging.StreamHandler(sys.stdout)
        ch.setLevel(logging.DEBUG)

        fh_fmt = '%(asctime)s %(levelname)8s %(message)s [%(filename)s:%(lineno)d]'
        #fh_fmt = '%(asctime)s - %(funcName)s - %(levelname)s - %(message)s'

        ch_fmt = '%(asctime)s %(levelname)8s %(message)s [%(filename)s:%(lineno)d]'
        #ch_fmt = '%(funcName)s - %(levelname)s - %(message)s'

        fh.setFormatter(logging.Formatter(fh_fmt))
        ch.setFormatter(logging.Formatter(ch_fmt))

        root = logging.getLogger()
        root.addHandler(fh)
        root.addHandler(ch)

为什么我导入的所有模块的默认级别都设置为警告。当我们使用log = logging.getLogger( name )导入我的根记录器时,为什么我必须为每个级别再次设置DEBUG级别?这是在具有不同模块的包中创建日志记录模块的最佳方法,还是有更好的解决方案?

1 个答案:

答案 0 :(得分:6)

让我们先来看看Handler.setLevel does

  

将此处理程序的阈值设置为lvl。记录不如lvl严重的消息将被忽略。创建处理程序时,级别设置为NOTSET(这会导致处理所有消息)。

忽略任何比lvl严重的消息。实际上,将其设置为DEBUG是没有意义的(除非您定义自己的日志级别),因为没有比调试更严重的消息。所以,这意味着处理程序不会忽略任何消息。

setLevel是正确的想法,但你在错误的对象上调用它。看看Logger.setLevel

  

将此记录器的阈值设置为lvl。记录不如lvl严重的消息将被忽略。创建记录器时,级别设置为NOTSET(当记录器是根记录器时会导致处理所有消息,或者当记录器是非root记录器时委托给父级)。请注意,根记录器的创建级别为WARNING。

     

术语“委托给父母”意味着如果记录器具有NOTSET级别,则遍历其祖先记录器链,直到找到具有NOTSET以外级别的祖先,或者到达根目录。

     

如果发现祖先的级别不是NOTSET,那么祖先的级别将被视为祖先搜索开始的记录器的有效级别,并用于确定如何处理日志记录事件。

您正在创建孩子,但他们都是根记录器的孩子。它们的级别设置为NOTSET,并传播到根,其默认值为WARNING。因此,您没有看到任何消息。

<强> TL; DR: 解决方案很简单:在记录器上设置级别,而不是处理程序。以下代码应该满足您的需求:

def start_logger():
    fh = logging.handlers.RotatingFileHandler('logger.log', 
                                              maxBytes=1000000, 
                                              backupCount=100)

    ch = logging.StreamHandler(sys.stdout)

    fh_fmt = '%(asctime)s %(levelname)8s %(message)s [%(filename)s:%(lineno)d]'
    #fh_fmt = '%(asctime)s - %(funcName)s - %(levelname)s - %(message)s'

    ch_fmt = '%(asctime)s %(levelname)8s %(message)s [%(filename)s:%(lineno)d]'
    #ch_fmt = '%(funcName)s - %(levelname)s - %(message)s'

    fh.setFormatter(logging.Formatter(fh_fmt))
    ch.setFormatter(logging.Formatter(ch_fmt))

    logging.basicConfig(level=logging.DEBUG)
    root = logging.getLogger()
    root.addHandler(fh)
    root.addHandler(ch)

一旦你这样做,你就不应该在生孩子时需要setLevel电话。

哦,并回答你的其他问题:这正是你应该使用日志库的方式。 (我实际上只是将所有内容记录到根记录器中,因为我不需要你开发的那种粒度,但是当你有一个案例时,你就是按照你应该做的那样。)

编辑:显然,setLevel似乎不能在根记录器上运行。相反,在访问根记录器之前,您必须设置basicConfig。在logging.basicConfig中设置级别将满足您的需求(至少,它在我的测试中有效)。请注意,这样做符合Logging from multiple modules中给出的示例,因此应解决您的问题。