找不到与记录器相对应的处理程序。

71

我是Python的新手。我正在尝试使用Python进行日志记录,并在尝试通过日志记录器实例打印一些警告时遇到了找不到日志处理程序的错误。以下是我尝试过的代码:

import logging
logger=logging.getLogger('logger')
logger.warning('The system may break down')

我遇到了这个错误"logger"找不到处理程序

让我困惑的是,当我第一次尝试使用logging打印警告,然后通过logger打印时,它可以正常工作,例如:

>>> import logging
>>> logging.warning('This is a WARNING!!!!')
WARNING:root:This is a WARNING!!!!
>>> 
>>> logger.warning('WARNING!!!!')
WARNING:logger:WARNING!!!!

有人能解释一下第二种情况发生了什么吗?


1
{btsdaf} - Trevor Boyd Smith
6个回答

79

调用logging.basicConfig()

>>> import logging
>>> logging.basicConfig()
>>> logger = logging.getLogger('logger')
>>> logger.warning('The system may break down')
WARNING:logger:The system may break down

谢谢分享!但我只是想知道为什么它在第二种情况下能够工作... - qwerty
5
如果日志未配置,logging.warning()会调用logging.basicConfig() - phd
1
如果您想添加信息日志,只需将级别设置为info即可:logger.setLevel(logging.INFO) - Shakeel

33

如果想要通过logger记录一些信息,在Python中至少需要向logger对象添加一个处理程序。默认情况下,logging模块中的debugwarn和其他函数将调用basicConfig,而basicConfig会将一个StreamHandler添加到root logger

建议为编写的模块添加所需的处理程序,这样做总是推荐的。

您可以参考官方Python文档,其中有一个很棒的教程,或者您可以自己查看logging模块的源代码。

简单地说,您可以通过Python shell中的以下方式检查源代码:

import logging
import inspect
print(inspect.getsource(logging))

最后,显式调用basicConfig将解决问题。
import logging
logging.basicConfig()
logger = logging.getLogger('logger')
logger.warning('The system may break down')

17

除了phd的答案外,调用 logging.basicConfig() 是一个方便的函数,它将为您获取一个默认的 StreamHandler 和一个 Formatter。如果您想快速拥有记录功能,这就足够了。您可以通过向 basicConfig 传递一些参数来自定义其行为:

添加有用的参数:在消息旁边输出时间戳

logger = logging.basicConfig(level=logging.DEBUG, 
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

对于大多数一次性需求, 这样做是可以的。如果你需要更多关于配置的控制,你可以通过自行定义记录器属性来添加更复杂的行为。

高级示例: 不使用basicConfig函数

import logging
logger = logging.getLogger("mylogger")
streamHandler = logging.StreamHandler()
streamHandler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
streamHandler.setFormatter(formatter)

logger.addHandler(streamHandler)

logger.info("Files copied")
logger.warning("disk quota exceeded")
>> 2017-12-06 11:11:12, 090 - mylogger - INFO Files copied
>> 2017-12-06 11:11:12, 091 - mylogger - WARNING disk quota exceeded
在一个更大的环境中,下一步将是从先前创建的日志记录器派生出一个新的日志记录器,以首先保留格式,并维护“日志层次结构”。
logger2 = logging.getLogger("mylogger.new")
logger2.info("New Logger info")
>> 2017-12-06 11:11:12, 091 - mylogger.new - New logger info

一个很好的参考是日志记录指南: https://docs.python.org/2/howto/logging-cookbook.html


'formatter' 行有一个错别字 - 缺少 '('. 花了我很长时间才明白为什么在尝试运行那个示例时会收到一个神秘的错误。 - Nowakus

1

0
为了完整起见:
为了使其在可能在其他地方或独立使用的模块级别上工作,您可以执行以下操作:
logger = logging.getLogger(__name__)

# create own logging handler if nobody changed the root logger.
if not logging.root.handlers and not logger.handlers:
    handler = logging.StreamHandler()
    handler.formatter = logging.Formatter('%(asctime)s %(funcName)s %(levelname)s: %(message)s')
    logger.addHandler(handler)

这样可以使模块独立运行,并避免在已经配置根记录器的上下文中使用时出现冲突。

请注意,帖子中描述的错误消息仅在Python 2中出现。如果在层次结构中未定义处理程序,则Python 3将消息打印到stdout。


0
如果您在使用sentry时遇到此错误(No handlers could be found for logger "sentry.errors"),可能是由于SNI支持的sentry bug引起的。
请查看https://github.com/getsentry/raven-python/issues/523以获取更多详细信息。一个快速解决方法是将DSN方案替换为threaded+requests+https
RAVEN_CONFIG = {
    'dsn': 'threaded+requests+https://xxxxxxxxxxxx@sentry.example.com/1',
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接