使用日志中的模块名称登录多个类

时间:2014-04-30 10:59:01

标签: python logging namespaces

我想使用日志记录模块而不是打印调试信息和文档。 目标是使用DEBUG级别在控制台上打印,并使用INFO级别登录到文件。

我阅读了很多关于日志记录模块的文档,食谱和其他教程,但无法弄清楚,我怎么能按照我想要的方式使用它。 (我在python25上)

我希望在日志文件中包含日志的模块名称。

文档说我应该使用logger = logging.getLogger(__name__)但是如何声明其他模块/包中的类中使用的记录器,因此它们使用与主记录器相同的处理程序?为了识别'父母',我可以使用logger = logging.getLogger(parent.child)但我在哪里知道谁调用了这个类/方法?`

下面的示例显示了我的问题,如果我运行此选项,输出将只有__main__登录并忽略Class中的日志

这是我的主文件:

# main.py

import logging
from module import Class

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

# create file handler which logs info messages
fh = logging.FileHandler('foo.log', 'w', 'utf-8')
fh.setLevel(logging.INFO)

# create console handler with a debug log level
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

# creating a formatter
formatter = logging.Formatter('- %(name)s - %(levelname)-8s: %(message)s')

# setting handler format
fh.setFormatter(formatter)
ch.setFormatter(formatter)

# add the handlers to the logger
logger.addHandler(fh)
logger.addHandler(ch)

if __name__ == '__main__':
    logger.info('Script starts')
    logger.info('calling class Class')
    c = Class()
    logger.info('calling c.do_something()')
    c.do_something()
    logger.info('calling c.try_something()')
    c.try_something()

模块:

# module.py

imnport logging

class Class:
    def __init__(self):
        self.logger = logging.getLogger(__name__) # What do I have to enter here?
        self.logger.info('creating an instance of Class')
        self.dict = {'a':'A'}
    def do_something(self):
        self.logger.debug('doing something')
        a = 1 + 1
        self.logger.debug('done doing something')
    def try_something(self):
        try:
            logging.debug(self.dict['b'])
        except KeyError, e:
            logging.exception(e)

控制台输出

- __main__ - INFO    : Script starts
- __main__ - INFO    : calling class Class
- __main__ - INFO    : calling c.do_something()
- __main__ - INFO    : calling c.try_something()
No handlers could be found for logger "module"

此外:有没有办法让模块名称在我的日志文件中显示日志,而不像上面那样在每个类中声明一个新的记录器?也像这样我每次想记录东西时都要去self.logger.info()。我希望在我的整个代码中使用logging.info()logger.info()

全球记录器或许是正确答案吗?但是,我不会得到日志中出现错误的模块......

我的最后一个问题:这是pythonic吗?或者是否有更好的建议来做正确的事情。

2 个答案:

答案 0 :(得分:12)

在您的主模块中,您在module.py中配置了名为'__main__'的记录器(或者__name__等同于您的记录器),而您正在使用不同的记录仪。您需要为每个模块配置记录器,或者您可以在主模块中配置根记录器(通过配置logging.getLogger()),默认情况下将应用于项目中的所有记录器。

我建议使用配置文件来配置记录器。此链接应该让您对良好做法有所了解:http://victorlin.me/posts/2012/08/26/good-logging-practice-in-python

编辑:在格式化程序中使用%(module)将模块名称包含在日志消息中。

答案 1 :(得分:5)

您的处理程序应该有一个全局记录器:

logger= logging.getLogger("myapp")
#configure handlers

然后,在每个模块上:

logger= logging.getLogger("myapp."+__name__)

您是否需要每类记录器取决于您 - 我见过的大多数项目(最多)每个模块有一个记录器。我的建议是,如果你不需要不同类别的不同处理程序,每个模块只需要一个记录器,或者每个项目都需要一个记录器 - 如果项目很小的话。

如果您需要更多日志上下文,请注意您可以使用格式化程序上的%(funcName)s打印当前函数名称