找不到记录器的处理程序

No handlers could be found for logger

我是 python 的新手。我正在尝试登录 python 并在尝试通过记录器实例打印一些警告时遇到 No handlers could be found for logger 错误。下面是我试过的代码

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!!!!

有人可以阐明第二种情况下发生的事情吗?

调用logging.basicConfig():

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

为了通过 logger 记录一些消息,在 Python 中至少应向 logger 对象添加一个处理程序。默认情况下,debugwarnlogging 模块中的其他函数将调用 basicConfig,后者又会向 root logger 添加一个 StreamHandler

总是 recommended 将所需的处理程序添加到您为模块编写的记录器对象中。

你可以参考official Python docs, which has an awesome tutorial或者你自己查看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')

除了 phd 的回答之外,调用 logging.basicConfig() 是一个方便的函数,它将为您提供默认值 StreamHandlerFormatter。如果您想快速拥有日志记录功能,这就足够了。您可以通过传递 basicConfig 一些参数来自定义它的行为:

Add Useful parameters: output timestamp alongside the message

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

这应该可以满足大多数一次性需求。如果您需要对配置进行更多控制,可以通过自己定义记录器的属性来添加更复杂的行为。

Sophisticated Example: without using the basicConfig function

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

在更大的环境中,下一步是从先前创建的记录器派生一个新的记录器,首先保持格式并维护 "log hierarchy"

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

如果您在使用 sentry (No handlers could be found for logger "sentry.errors") 时遇到此错误,可能是由于 SNI 支持的哨兵错误。

查看 https://github.com/getsentry/raven-python/issues/523 了解更多详情。一个快速的解决方法是用 threaded+requests+https:

替换 DSN 方案
RAVEN_CONFIG = {
    'dsn': 'threaded+requests+https://xxxxxxxxxxxx@sentry.example.com/1',
}

为了完整起见:

为了使它在模块级别上工作,可以在其他地方或独立使用,你可以这样做

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)

这允许 运行 模块独立并避免在已经配置根记录器的上下文中使用时发生冲突。

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

参见 What happens if no configuration is provided。 Python 3.2 及更高版本中不应发生此错误。