如何在多个模块中使用python日志记录

时间:2013-04-03 06:15:52

标签: python logging

我想知道在Python应用程序中执行日志记录的标准设置是什么。

我正在使用Logging类,我编写了自己的logger类来实例化Logging类。我的主要然后实例化我的记录器包装类。但是,我的main实例化其他类,我希望其他类也能够通过main中的logger对象写入日志文件。

如何使该logger对象可以被其他类调用?这几乎就像我们需要某种静态记录器对象才能使它工作。

我想问题的长短是:如何在代码结构中实现日志记录,以便从main中实例化的所有类都可以写入同一个日志文件?我是否只需要在指向同一文件的每个类中创建一个新的日志记录对象?

2 个答案:

答案 0 :(得分:27)

我不知道你对Logging类的意思 - 在Python的内置日志记录中没有这样的类。你真的不需要包装器:这是一个如何从你编写的任意类中进行记录的例子:

import logging

# This class could be imported from a utility module
class LogMixin(object):
    @property
    def logger(self):
        name = '.'.join([__name__, self.__class__.__name__])
        return logging.getLogger(name)


# This class is just there to show that you can use a mixin like LogMixin
class Base(object):
    pass

# This could be in a module separate from B
class A(Base, LogMixin):
    def __init__(self):
        # Example of logging from a method in one of your classes
        self.logger.debug('Hello from A')

# This could be in a module separate from A
class B(Base, LogMixin):
    def __init__(self):
        # Another example of logging from a method in one of your classes
        self.logger.debug('Hello from B')

def main():
    # Do some work to exercise logging
    a = A()
    b = B()
    with open('myapp.log') as f:
        print('Log file contents:')
        print(f.read())

if __name__ == '__main__':
    # Configure only in your main program clause
    logging.basicConfig(level=logging.DEBUG,
                        filename='myapp.log', filemode='w',
                        format='%(name)s %(levelname)s %(message)s')
    main()

通常没有必要在类级别拥有记录器:在Python中,与Java不同,程序(de)组合的单位是模块。但是,正如我上面所示,没有什么可以阻止你这样做。该脚本在运行时显示:

Log file contents:
__main__.A DEBUG Hello from A
__main__.B DEBUG Hello from B

请注意,两个类中的代码都记录到同一个文件myapp.log中。即使A和B在不同的模块中也可以使用。

答案 1 :(得分:6)

尝试使用logging.getLogger()来获取日志记录对象实例:

http://docs.python.org/3/library/logging.html#logging.getLogger

  

对具有给定名称的此函数的所有调用都返回相同的记录器实例。这意味着记录器实例永远不需要在应用程序的不同部分之间传递。

<强>更新

建议的方法是使用getLogger()函数并对其进行配置(设置处理程序,格式化程序等等):

# main.py
import logging
import lib


def main():
    logger = logging.getLogger('custom_logger')
    logger.setLevel(logging.INFO)
    logger.addHandler(logging.FileHandler('test.log'))
    logger.info('logged from main module')
    lib.log()

if __name__ == '__main__':
    main()

# lib.py
import logging


def log():
    logger = logging.getLogger('custom_logger')
    logger.info('logged from lib module')

如果您真的需要扩展记录器类,请查看 logging.setLoggerClass(klass)

更新2

如何在不更改Logging类的情况下添加自定义日志记录级别的示例:

# main.py
import logging
import lib


# Extend Logger class
CUSTOM_LEVEL_NUM = 9
logging.addLevelName(CUSTOM_LEVEL_NUM, 'CUSTOM')
def custom(self, msg, *args, **kwargs):
    self._log(CUSTOM_LEVEL_NUM, msg, args, **kwargs)
logging.Logger.custom = custom

# Do global logger instance setup
logger = logging.getLogger('custom_logger')
logger.setLevel(logging.INFO)
logger.addHandler(logging.FileHandler('test.log'))


def main():
    logger = logging.getLogger('custom_logger')
    logger.custom('logged from main module')
    lib.log()

if __name__ == '__main__':
    main()

请注意,建议不要添加自定义级别:http://docs.python.org/2/howto/logging.html#custom-levels

定义自定义处理程序并且可能使用多个记录器可能可以满足您的其他要求:可选输出到stderr。