Python - 避免在函数之间传递记录器引用?

vic*_*ooi 49 python logging

我有一个使用内置的简单Python脚本logging.

我正在配置函数内的日志记录.基本结构将是这样的:

#!/usr/bin/env python
import logging
import ...

def configure_logging():
    logger = logging.getLogger("my logger")
    logger.setLevel(logging.DEBUG)
    # Format for our loglines
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    # Setup console logging
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    ch.setFormatter(formatter)
    logger.addHandler(ch)
    # Setup file logging as well
    fh = logging.FileHandler(LOG_FILENAME)
    fh.setLevel(logging.DEBUG)
    fh.setFormatter(formatter)
    logger.addHandler(fh)
    return logger

def count_parrots():
    ...
    logger.debug??

if __name__ == '__main__':
    logger = configure_logging()
    logger.debug("I'm a log file")
    parrots = count_parrots()
Run Code Online (Sandbox Code Playgroud)

我可以从内部调用logger __main__.但是,如何从count_parrots()函数内部调用logger?处理像这样的记录器的最pythonic方法是什么?

Yan*_*eau 40

您可以使用root(默认)记录器,从而使用模块级别函数logging.debug,...或者使用它来获取函数中的记录器.实际上,该getLogger函数是一个类似工厂的函数,具有注册表(类似单例),即它总是返回给定记录器名称的相同实例.因此,您只需使用即可将您的记录器输入count_parrots

logger = logging.getLogger("my logger") 
Run Code Online (Sandbox Code Playgroud)

在开始.但是,惯例是为记录器使用点分层名称.请参阅http://docs.python.org/library/logging.html#logging.getLogger

编辑:

您可以使用装饰器将记录行为添加到各个函数,例如:

def debug(loggername):
    logger = logging.getLogger(loggername) 
    def log_(enter_message, exit_message=None):
        def wrapper(f):
            def wrapped(*args, **kargs):
                logger.debug(enter_message)
                r = f(*args, **kargs)
                if exit_message:
                    logger.debug(exit_message)
                return r
            return wrapped
        return wrapper
    return log_

my_debug = debug('my.logger')

@my_debug('enter foo', 'exit foo')
def foo(a, b):
    return a+b
Run Code Online (Sandbox Code Playgroud)

您可以"硬编码"记录器名称并删除顶级闭包和my_debug.

  • 这个答案显示了Python`logging`模块的所有错误...... (18认同)
  • 好的,所以我可以在每个需要记录的函数的开头调用logging.getLogger.肯定有点浪费和重复吗?很公平.或者我会更好地去面向对象,并试图将整个过程变成一个类?(这是一个非常普遍的问题,我知道,我只是在寻找Python世界中已经完成的事情). (10认同)
  • 我很好奇人们认为这种横切模块需要什么替代方案?我不知道从通用设计的角度来看logging.getLogger有什么问题。看起来很漂亮的样板内容。 (2认同)

sat*_*esh 15

你可以这样做:

logger = logging.getLogger("my logger") 
Run Code Online (Sandbox Code Playgroud)

在你的count_parrots()方法.当您传递先前使用的名称(即"我的记录器")时,日志记录模块将返回与该名称对应的相同实例.

更新:从日志教程 (emphais mine)

getLogger()返回对具有指定名称的记录器实例的引用(如果已提供),如果不是则返回root.名称是以句点分隔的层次结构.对具有相同名称的getLogger()的多次调用将返回对同一记录器对象的引用.


nco*_*lan 9

处理日志记录的典型方法是将每个模块的记录器存储在全局变量中.然后,该模块中的任何函数和方法只引用相同的logger实例.

这在文档中的高级日志记录教程的介绍中进行了简要讨论:http: //docs.python.org/howto/logging.html#advanced-logging-tutorial

可以将记录器实例作为参数传递,但这样做通常很少见.

  • @MatthewCornell 你的意思是`logger = logging.getLogger(__name__)`。 (2认同)