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

Gre*_*egH 10 python logging

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

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

如何使该logger对象可以被其他类调用?这几乎就像我们需要某种静态记录器对象来实现它.

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

Vin*_*jip 28

我不知道你的意思是什么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()
Run Code Online (Sandbox Code Playgroud)

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

Log file contents:
__main__.A DEBUG Hello from A
__main__.B DEBUG Hello from B
Run Code Online (Sandbox Code Playgroud)

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

  • 如果在其他模块中使用 mixin 类,`__name__` 是不正确的。 (2认同)

gon*_*onz 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')
Run Code Online (Sandbox Code Playgroud)

如果你真的需要扩展logger类,请看一下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()
Run Code Online (Sandbox Code Playgroud)

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

定义自定义处理程序并且可能使用多个记录器可以为您的其他要求提供技巧:可选输出到stderr.