在Python

时间:2017-11-20 13:13:54

标签: python logging

我有以下应用程序结构:

./utils.py
def do_something(logger=None):
    if not logger:
        logger = logging.getLogger(__name__)

    print('hello')
    logger.debug('test')

./one.py
from utils import do_something
logger = logging.getLogger(__name__)
do_something(logger=logger)

./two.py
from utils import do_something
logger = logging.getLogger(__name__)
do_something(logger=logger)

现在运行,日志输出将显示使用函数(onetwo)而不是utils的相应模块的名称。然后,我使用此信息(记录器的名称)来过滤消息。

有没有办法做到这一点,而不必通过记录器作为参数?我是否必须基本上反省调用函数并基于此初始化记录器?这种配方的常见解决方案是什么,当在整个代码库中使用一个函数但是记录器应该是那些调用函数的函数?

3 个答案:

答案 0 :(得分:1)

变量do_something()是全局的,可以从logger = logging.getLogger(__name__) def do_something(): x = logger 函数内部访问,如下所示:

logger

仔细阅读后:

  

当一种功能时,这种配方的常见解决方案是什么   在整个代码库中使用,但记录器应该是那些   调用函数?

simple english中会是:

  

如何从导入的函数do_something()访问全局变量from utils import do_something logger = logging.getLogger(__name__) do_something() # logger global is not visible in do_something() do_something(logger=logger) # the only way

我的结论是没有别的办法! 您必须将记录器作为此特定情况的参数传递。

{{1}}

答案 1 :(得分:1)

传递logger作为参数对我来说很好。但是如果你有多次调用do_something,那么在每次调用中传递相同的记录器不仅太冗长而且容易出错 - 你可能会错误地传递错误的记录器。此外,虽然你确实需要让do_something知道记录器,但是在你调用它的时候这样做可能没有意义 - 你想要做一些事情,而不是弄乱记录器。 OOP救援:使do_something成为类的方法,并在实例化类时传递记录器,然后您不需要将它传递给方法。

# utils.py
class UsefulObject:
    def __init__(self, logger):
        self._logger = logger

    def do_something(self):
        print('hello')
        self._logger.debug('test')

现在,在客户端模块中,您可以创建UsefulObject的实例,并且可以在其上调用.do_something,而无需每次都传递记录器。

# one.py
from utils import UsefulObject
logger = logging.getLogger(__name__)
useful_object = UsefulObject(logger)  # do this once
# ...
useful_object.do_something()  # do this many times, do not pass the logger

答案 2 :(得分:0)

如果您不喜欢现有的解决方案,这是一种神奇的方法:

def do_something():
    logger = inspect.currentframe().f_back.f_globals['log']
    ...

然后,调用函数必须具有一个名为log的全局变量。