从库模块的Python日志记录
问题描述:
我想在我的Python库模块中设置通用日志记录,以便它们使用调用模块中配置的日志记录器而不必硬编码记录器名称。我在调用模块中看到了很多使用logging.basicConfig()
的示例,并在库模块中调用logging.debug()
,但在配置我自己的StreamHandler时不起作用。我究竟做错了什么?从库模块的Python日志记录
这是我的电话模块:
import logging, logging.handlers
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
consolehandler = logging.StreamHandler()
consoleformatter = logging.Formatter('[%(name)s] %(levelname)s %(message)s')
consolehandler.setFormatter(consoleformatter)
logger.addHandler(consolehandler)
import libmodule
def run():
logger.info("message from calling module")
libmodule.say("message from library module")
我在libmodule.py试过这样:
import logging
def say(msg):
logging.info(msg)
这:
import logging
logger = logging.getLogger()
def say(msg):
logger.info(msg)
但在这两种情况下,当我调用运行(),我得到这个输出:
[callingmodule] INFO message from calling module
但期待这样的:
[callingmodule] INFO message from calling module
[callingmodule] INFO message from library module
答
这是因为在一审中,您可以通过名字得到一个记录器,并在第二,你只需要使用getLogger()
,它返回根记录。哪个不是同一个,并且没有安装您的自定义流处理程序。
的更简单的方式做,这是遵循文档here指导:
“多次调用getLogger()具有相同的名称将始终返回 参照同Logger对象。”
换句话说,如果你只是在这两个地方使用getLogger('my_common_name')
,然后他们两个会自动指向同一个记录器,即使你在一个地方定制它。
补充:如果你想捕捉从父记录器,那么你会做这样的事情在你的库:
# In libmodule
_log = None
def initLogger(logger=None):
global _log
if logger != None:
_log = logger
else:
import logging
_log = logging.getLogger()
# Later in the module
def say(message):
_log.info(message)
父模块中
则:
# In the parent module
mylog = a logger i set up
import libmodule
libmodule.initLogger(mylog)
应使他们都指向同一个记录器。
感谢您回复Corley。这将意味着硬编码我的库代码中的通用名称,并且只会在库的用户选择相同的通用名称时才起作用。 – 2014-10-16 15:12:15
好吧,你现在正在这样做,有点(都在查看中央日志记录模块并寻找硬代码记录器,一个是'__file__',另一个是根目录;两者都不直视对方)。你是否试图允许用户将图书馆记录器重新路由到他们自己的?做这件事的标准方法是,有一个'initLogger()'函数来初始化库记录器,你可以传入一个记录器。如果没有记录器通过,它创建它自己的。类似的东西。 – 2014-10-16 15:34:25
你说得对,我想把图书馆记录器重新路由到用户配置的记录器中,但我希望能自动完成。 'initLogger()'方法听起来很有趣。有没有可以指点我的例子? – 2014-10-16 15:46:39