无法使用Python日志模块登录到两个不同的位置

无法使用Python日志模块登录到两个不同的位置,python,Python,请原谅,我仍在学习如何使用日志记录模块。因此,我有两个处理程序,一个用于将所有内容记录到文件中,另一个专门用于在触发Hipchat时记录消息 我不太明白有根和非根记录器意味着什么。如下所示,它会将我想要的内容写入日志文件,并在聊天室中显示这两条消息。所以我找到了另一个堆栈帖子,上面写着创建两个多个“非根记录器”。所以我尝试了logger=logging.getLogger('test1')和hipchat\u logger=logging.getLogger('test2'),但是hipchat

请原谅,我仍在学习如何使用
日志记录
模块。因此,我有两个处理程序,一个用于将所有内容记录到文件中,另一个专门用于在触发Hipchat时记录消息

我不太明白有根和非根记录器意味着什么。如下所示,它会将我想要的内容写入日志文件,并在聊天室中显示这两条消息。所以我找到了另一个堆栈帖子,上面写着创建两个多个“非根记录器”。所以我尝试了
logger=logging.getLogger('test1')
hipchat\u logger=logging.getLogger('test2')
,但是hipchat中没有消息(它确实写入日志文件)


问题出在前两行。“对具有相同名称的getLogger()的多次调用将始终返回对相同记录器对象的引用。”,cf

因此,解决方案将是(在评论中讨论后修改):

编辑

在对这个主题进行更多研究之后:问题当然不是缺少根记录器。存在以下问题:

将忽略比lvl严重的日志消息。创建记录器时,级别设置为NOTSET(当记录器为根记录器时,会处理所有消息;当记录器为非根记录器时,会委托给父记录器)。请注意,根记录器是使用级别警告创建的

那么这里发生了什么

# implicit root logger with loglevel WARNING

# both child-logger: loglevel NOTSET
logger = logging.getLogger('file')
hipchat_logger = logging.getLogger('hipchat')

# ...create and add file handler...

# change 'file'-loglevel to DEBUG
logger.setLevel(logging.DEBUG)

# ...create hipchat handler...

# change loglevel of the handler(!) to DEBUG.
# 'hipchat'-loglevel is still NOTSET
hipchat_handler.setLevel(logging.DEBUG)

# ...add hipchat handler ...

# logger -> loglevel DEBUG -> INFO gets logged.
logger.info("Hi, this is a test. I should not see this in Hipchat")

# hipchat_logger -> loglevel NOTSET -> delegate to root-logger
# root-logger -> loglevel WARNING -> INFO not logged (being below threshold)
hipchat_logger.info("Hi, display me in Hipchat")
因此,要解决这个问题,可以显式地将root logger的loglevel设置为DEBUG(如上面的代码所示)。或者只需相应地设置第二个记录器的日志级别:

hipchat_logger.setLevel(logging.DEBUG)

还有一个问题可能会在别处得到回答:

代码问题之一是多次调用
logging.getLogger()
返回同一个记录器

# both of these are same logger instances
logger = logging.getLogger()    
hipchat_logger = logging.getLogger()
要获得两个不同的实例,请为不同的记录器指定不同的名称。另外,如果没有name参数,您将获得根记录器

root_logger = logging.getLogger()

logger = logging.getLogger("file")
hipchat_logger = logging.getLogger("hipchat")

#now getting the logger with same name will return same logger
this_is_same_as_logger = logging.getLogger("file")

这是否仅适用于HipChatLogger?您的意思是,如果不使用
logger
处理程序,则是这样。仅当我有多个处理程序时才使用。
assert logger是hipchat\u logger
→ True表示您从对
logging.getlogger()
的两个(静态)调用中获得相同的记录器。你需要实例化另一个记录器,比如说,我刚刚看了代码,但是文本说,你做了我们建议的所有事情。因此,也许可以尝试类似于
logger=logging.getLogger()
hipchat\u logger=logging.getLogger('hipchat')
?我已经尝试过了,请阅读示例代码之前的最后一句话。@luckytaxi正如您所理解并在我的答案中所写的那样。。。你必须有一个根记录器的实例。啊,好吧,我没有意识到我必须设置一个根记录器。我见过的大多数例子都有基于参数的记录器。。。我认为只有在同一模块中需要多个记录器时才会发生这种情况。。。可能是为了保持正确的传播。我已经试过了,请阅读示例代码之前的最后一句话。@LuckyTaxip是的,我意识到了,正如你在问题中所评论的。我让它工作了。你在评论中的解决方案有效:-)如果你想修改你的答案,我会接受。我将
记录器
处理程序留空,并将一个名称传递给
hipchat\u记录器
处理程序。好的,这很好。不过,我想知道为什么“两个非根解决方案”不适用于hipchat。我用两个子记录器做了一个测试,这很有效(Python2.7)。哇,谢谢你的额外研究和解释。现在完全有道理了。
# both of these are same logger instances
logger = logging.getLogger()    
hipchat_logger = logging.getLogger()
root_logger = logging.getLogger()

logger = logging.getLogger("file")
hipchat_logger = logging.getLogger("hipchat")

#now getting the logger with same name will return same logger
this_is_same_as_logger = logging.getLogger("file")