登录模块:无法找到记录器的处理程序

时间:2018-03-28 12:22:23

标签: python logging

我正在尝试使用在可执行文件中配置的记录器启用模块中的日志记录。

根据documentation

  

命名记录器时使用的一个很好的约定是在每个使用日志记录的模块中使用模块级记录器,命名如下:

logger = logging.getLogger(__name__)

我已经遵循了这一点,在我的foo模块中创建了一个模块级记录器:

模块foo

import logging

logger = logging.getLogger(__name__)

class Foo():
    def __init__(self):
        logger.info("hello world")

再次,根据documentation

  

使用调用上面列出的配置方法的Python代码显式创建记录器,处理程序和格式化程序。

在我的可执行文件中,我导入foo并设置记录器,基本上是上面文档链接示例的复制粘贴:

可执行

import logging
from foo import foo

if __name__ == '__main__':

    # create logger
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)

    # create console handler and set level to debug
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)

    # add ch to logger
    logger.addHandler(ch)

    logger.info('start')

    f = foo.Foo()

我从可执行文件中看到了日志语句,但我的基于模块的记录器不起作用:

start
No handlers could be found for logger "foo.foo"

我做错了什么?

修改

我尝试在我的可执行文件中使用basicConfig,根据documentation执行以下操作:

  

通过创建具有默认StreamHandler的{​​{1}}并将其添加到根记录器来为日志记录系统进行基本配置

可执行

Formatter

现在登录我的模块有效!

让我感到困惑的是,在我之前的示例中,我创建了import logging from foo import foo if __name__ == '__main__': # create logger logger = logging.getLogger(__name__) ... (same as above) ... logging.basicConfig(level=logging.DEBUG) logger.info('start') f = foo.Foo() 并将其添加到根记录器。

所以我想我的问题应该是:

什么是StreamHandler做哪些显式调用日志配置api不是?

2 个答案:

答案 0 :(得分:1)

您还需要将处理程序分配给Foo模块记录器,因为它们使用不同的记录器对象:

import logging

logger = logging.getLogger(__name__)
sh = logging.StreamHandler()
logger.setLevel(logging.DEBUG)
logger.addHandler(sh)

class Foo():
    def __init__(self):
        logger.info("hello world")

==================== RESTART: C:\Python27\tests\test2.py ====================
start
hello world

或者您可以使用日志记录模块中的basicConfig函数来更改根记录器和新记录器的默认值:

if __name__ == '__main__':
    sh = logging.StreamHandler()
    logging.basicConfig(level=logging.DEBUG)
    root = logging.getLogger(__name__)
    root.info('start')
    f = Foo()

一个很好的日志记录资源 - Python Logging Cookbook

根据新问题更新:

  

通过使用默认Formatter创建StreamHandler并将其添加到根记录器来为日志记录系统进行基本配置。如果没有为根记录器定义处理程序,函数debug(),info(),warning(),error()和critical()将自动调用basicConfig()。

在您的代码中,每个模块都有自己的记录器对象。您需要为每个指定处理程序和配置。基本配置基本上为您设置了一些默认值 - 如果您没有明确说明它们。所有记录器对象都是从根记录器派生的,因此您可以更改根记录器的默认值,然后新的记录器派生它。

答案 1 :(得分:0)

您需要在导入其他模块之前配置根记录器,这些模块将使用它作为工厂来制作本地记录器实例。

在获取子记录器之前更改您的可执行文件以配置根记录器

import logging
# root logger must be configured before loading child modules which use it
#logging.basicConfig(level=logging.DEBUG)
root_logger = logging.getLogger()
# create console handler and set level to debug
console = logging.StreamHandler()
console.setLevel(logging.DEBUG)
console_format = '%(asctime)15s %(levelname)-8s [%(filename)s:%(lineno)s %(funcName)s] %(message)s'
console_formatter = logging.Formatter(console_format)
console.setFormatter(console_formatter)
root_logger.addHandler(console)

from foo import foo

# create module specific logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

if __name__ == '__main__':

    logger.info('start')

    f = foo.Foo()

那么你的子模块可以是这样的:

import logging

# create module specific logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

class Foo():
    def __init__(self):
        logger.info("hello world")