动态Python日志记录的想法
我有一个应用程序,它会根据外部参数运行多个主应用的实例。主应用会导入一些库,而这些库又会导入其他库。它们都有一个全局的
LOGGER = logging.getLogger('module_name')
这个日志记录器被设置为文件处理器,所以所有的日志都会写入一个外部文件(所有日志都写在同一个文件里)。现在我想根据传给主应用的某个名称,把日志写入不同的文件。我需要类似这样的东西:
LOGGER = logging.getLogger(dynamic_criteria_name)
这样的话,就会生成多个日志文件,比如 dynamic_criteria_name.log,dynamic_criteria_name.log 等等。每当从任何模块调用日志记录器时,它应该根据调用时的条件写入正确的文件。
但问题是,LOGGER 是全局的。我可以把日志记录器或者 dynamic_criteria_name
传给每个函数来写日志,但这样感觉不太对劲。也许我只是有点多虑!我有一些模块,有时候里面只有函数。我不想到处传递日志记录器。
我考虑过 AOP(面向切面编程)一段时间,但我觉得这并不完全适用,因为它是动态生成的,日志记录器在我看来是跨切面的,但仅限于主应用的一个实例。我也想过其他方法来处理全局状态,但我觉得动态的特性让这一切在我脑海中变得不可能。
下面是伪代码(我还没试过运行它),但我觉得它能更好地解释我在说什么。正如你所看到的,module_1 导入了 module_2 和 module_3,它们都有一个全局的 LOGGER,而 module_3 又调用了 module_4。我想知道是否可以从 module_2 或 module_3 写入单独的日志文件,而不需要将名称显式传递给每个导入模块的函数。我可以给日志记录器添加多个处理器,使用不同的文件名,但在目前它们都是全局的,我该如何从另一个模块引用正确的日志记录器呢?
# module_1.py
import logging
import time
import module_2
import module_3
LOGGER = logging.getLogger()
def start_main_loop(name):
while True:
module_2.say_boo()
module_3.say_foo()
LOGGER.debug('Sleeping...')
time.sleep(10)
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
for i in xrange(10):
start_main_loop(i)
#----------------------------------------------------
# module_2.py
import logging
LOGGER = logging.getLogger()
def say_boo():
msg = 'boo'
LOGGER.debug(msg)
LOGGER.debug(say_twice(msg))
def say_twice(msg):
LOGGER.debug('Called say twice')
return msg * 2
#----------------------------------------------------
# module_3.py
import logging
import module_4
LOGGER = logging.getLogger()
def say_foo():
msg = 'foo'
LOGGER.debug(msg)
LOGGER.debug(say_twice(msg))
module_4.say_bar()
def say_twice(msg):
LOGGER.debug('Called say twice')
return msg * 2
#----------------------------------------------------
# module_4.py
import logging
LOGGER = logging.getLogger()
def say_bar():
msg = 'bar'
LOGGER.debug(msg)
我愿意探索任何人可能有的想法。希望我解释得够清楚,如果不清楚,请告诉我,我可以重新表述问题。谢谢!
1 个回答
你不需要到处传递日志记录器,因为日志记录器是单例的。也就是说,如果多个模块的代码都调用 getLogger('foo')
,每次调用都会返回同一个实例。所以没有必要把日志记录器的实例传来传去。一般来说,日志记录器的名字可以告诉你日志是从哪里来的,所以使用 __name__
的值是最合适的。你可以在一个名为 foo
的模块中,把日志记录到一个叫 bar
的日志记录器里——这没有什么限制,但在实际使用中,这样做并不是特别有用。
听起来使用面向切面编程(AOP)有点过于复杂。与其到处传递日志记录器的名字,不如考虑给根日志记录器添加多个处理器,每个处理器上设置特定的过滤器,这样可以根据你的需求确保特定的日志信息写入特定的文件。