如何在Python中配置日志记录

dex*_*vip 31 python logging python-2.7

我是Python新手,刚开始一个项目.我习惯log4j在Java中使用,我想像在Java中一样在Python中记录所有模块和类.

在Java中,我在src文件夹中有一个日志配置文件,log4j.properties如下所示:

log4j.rootLogger=DEBUG, Console, fileout

log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d{dd/MM/yyyy HH:mm:ss} %5p [%t] (%F:%L) - %m%n

log4j.appender.fileout=org.apache.log4j.RollingFileAppender
log4j.appender.fileout.File=servidor.log
log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
log4j.appender.fileout.layout.ConversionPattern=%d{dd/MM/yyyy HH:mm:ss} (%F:%L) %p %t %c - %m%n
Run Code Online (Sandbox Code Playgroud)

它记录到控制台和文件.

在我的类中,我只需要导入log4j并添加一个静态属性来恢复已log4j加载配置的记录器,然后所有类都将登录到控制台和文件中.配置文件由名称自动加载.例如:

import org.apache.log4j.Logger;

public class Main {
    public static Logger logger = Logger.getLogger(Main.class);
    public static void main(String[] args) {
        logger.info("Hello");
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我在使用Python设置日志记录时遇到问题,我已经阅读了文档,但我找不到在许多模块/类中使用它的方法.我怎样才能以简单的方式设置Python日志记录,以便在每个模块/类中没有代码的情况下记录我的模块和类?是否有可能重现我在Python中编写的相同代码?

Tor*_*cht 40

实际上在Python中它看起来非常相似.有不同的方法来做到这一点.我通常创建一个非常简单的记录器类:

import os
import logging 
import settings   # alternativly from whereever import settings  

class Logger(object):

    def __init__(self, name):
        name = name.replace('.log','')
        logger = logging.getLogger('log_namespace.%s' % name)    # log_namespace can be replaced with your namespace 
        logger.setLevel(logging.DEBUG)
        if not logger.handlers:
            file_name = os.path.join(settings.LOGGING_DIR, '%s.log' % name)    # usually I keep the LOGGING_DIR defined in some global settings file
            handler = logging.FileHandler(file_name)
            formatter = logging.Formatter('%(asctime)s %(levelname)s:%(name)s %(message)s')
            handler.setFormatter(formatter)
            handler.setLevel(logging.DEBUG)
            logger.addHandler(handler)
        self._logger = logger

    def get(self):
        return self._logger
Run Code Online (Sandbox Code Playgroud)

然后,如果我想在类或模块中记录某些东西,我只需导入记录器并创建一个实例.传递类名将为每个类创建一个文件.然后,记录器可以通过调试,信息,错误等将消息记录到其文件中:

from module_where_logger_is_defined import Logger

class MyCustomClass(object):

    def __init__(self):
        self.logger = Logger(self.__class__.__name__).get()   # accessing the "private" variables for each class

    def do_something():
        ...
        self.logger.info('Hello')

    def raise_error():
        ...
        self.logger.error('some error message')
Run Code Online (Sandbox Code Playgroud)

更新的答案

多年来,我改变了我使用Python日志的方式.主要基于良好实践,我在应用程序启动期间首先加载的任何模块中配置整个应用程序的日志记录,然后在每个文件中使用单独的记录器.例:


# app.py (runs when application starts)

import logging
import os.path

def main():
    logging_config = {
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'standard': {
                'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
            },
        },
        'handlers': {
            'default_handler': {
                'class': 'logging.handlers.FileHandler',
                'level': 'DEBUG',
                'formatter': 'standard',
                'filename': os.path.join('logs', 'application.log'),
                'encoding': 'utf8'
            },
        },
        'loggers': {
            '': {
                'handlers': ['default_handler'],
                'level': 'DEBUG',
                'propagate': False
            }
        }
    }
    logging.config.dictConfig(logging_config)
    # start application ...

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

# submodule.py (any application module used later in the application)

import logging

# define top level module logger
logger = logging.getLogger(__name__)

def do_something():
    # application code ...
    logger.info('Something happended')
    # more code ...
    try:
        # something which might break
    except SomeError:
        logger.exception('Something broke')
        # handle exception
    # more code ...
Run Code Online (Sandbox Code Playgroud)

以上是推荐的方法.每个模块都定义了自己的记录器,并且可以__name__在检查日志时根据属性轻松识别哪个模块中记录了哪个消息.这将从我的原始答案中删除样板,而是使用logging.configPython标准库中的模块.


Mar*_*eth 12

文档提供了在多个模块中使用记录器的一个很好的示例.基本上,您在程序开始时设置一次日志记录.然后,将日志记录模块导入到要记录的任何位置,并使用它.

myapp.py

import logging
import mylib

def main():
    logging.basicConfig(filename='myapp.log', level=logging.INFO)
    logging.info('Started')
    mylib.do_something()
    logging.info('Finished')

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

mylib.py

import logging

def do_something():
    logging.info('Doing something')
Run Code Online (Sandbox Code Playgroud)

此示例显示了一个非常简单的记录器设置,但您可以非常轻松地使用各种方法配置日志记录以设置更高级的方案.

  • 我强烈建议您询问有关Python范围问题的新问题(或搜索类似问题).过度简化,"范围"一词指的是语言用来确定哪个对象变量(在本例中为`logging`变量)所引用的规则.Python的范围是这样的,模块不会隐式地查看其他模块.这是一件好事:通过强制`mylib.py`明确定义`logging`意味着什么,可以更改`myapp.py`(例如,从中删除日志语句),而不必担心`mylib .py`由于这种变化而破裂. (3认同)