Python日志记录不输出任何内容


93

在我正在编写的python脚本中,我试图使用日志记录模块记录事件。我有以下代码来配置记录器:

ERROR_FORMAT = "%(levelname)s at %(asctime)s in %(funcName)s in %(filename) at line %(lineno)d: %(message)s"
DEBUG_FORMAT = "%(lineno)d in %(filename)s at %(asctime)s: %(message)s"
LOG_CONFIG = {'version':1,
              'formatters':{'error':{'format':ERROR_FORMAT},
                            'debug':{'format':DEBUG_FORMAT}},
              'handlers':{'console':{'class':'logging.StreamHandler',
                                     'formatter':'debug',
                                     'level':logging.DEBUG},
                          'file':{'class':'logging.FileHandler',
                                  'filename':'/usr/local/logs/DatabaseUpdate.log',
                                  'formatter':'error',
                                  'level':logging.ERROR}},
              'root':{'handlers':('console', 'file')}}
logging.config.dictConfig(LOG_CONFIG)

当我尝试运行时logging.debug("Some string"),即使文档中的此页面显示logging.debug应该由root logger输出消息,但也没有输出到控制台。为什么我的程序什么都不输出,我该如何解决?

Answers:


98

默认的日志记录级别是警告。由于您尚未更改级别,因此根记录器的级别仍处于警告状态。这意味着它将忽略任何级别低于警告的日志记录,包括调试日志记录。

教程对此进行了说明:

import logging
logging.warning('Watch out!') # will print a message to the console
logging.info('I told you so') # will not print anything

“信息”行不打印任何内容,因为级别高于信息。

要更改级别,只需在根记录器中进行设置:

'root':{'handlers':('console', 'file'), 'level':'DEBUG'}

换句话说,仅用level = DEBUG定义处理程序是不够的,实际的日志记录级别也必须是DEBUG才能使其输出任何内容。


6
该文档说,其默认级别为NOTSET,该级别为0,应该输出所有内容...为什么不是这样?

@Ben在哪里说?我所看到的就是“默认级别为WARNING,这意味着将仅跟踪此级别及更高级别的事件,除非将日志记录程序包配置为执行其他操作。”
Omri Barel '10


1
根据文档的@Ben,遍历记录器以查找具有level != NOTSET或根的第一个父级(如果未找到)。WARNING默认情况下,根目录具有级别。这是在您链接到(Logger.setLevel)的部分中编写的。
Omri Barel '17

5
请记住,导入后logginglogging.basicConfig()至少需要调用一次。否则,您可能会对子记录器无法打印任何内容感到非常惊讶。根记录器上的记录功能会延迟调用它。
休伯特·格热斯科维克

57

许多年后,Python记录器似乎仍然存在可用性问题。以下是一些示例说明:

import logging
# This sets the root logger to write to stdout (your console).
# Your script/app needs to call this somewhere at least once.
logging.basicConfig()

# By default the root logger is set to WARNING and all loggers you define
# inherit that value. Here we set the root logger to NOTSET. This logging
# level is automatically inherited by all existing and new sub-loggers
# that do not set a less verbose level.
logging.root.setLevel(logging.NOTSET)

# The following line sets the root logger level as well.
# It's equivalent to both previous statements combined:
logging.basicConfig(level=logging.NOTSET)


# You can either share the `logger` object between all your files or the
# name handle (here `my-app`) and call `logging.getLogger` with it.
# The result is the same.
handle = "my-app"
logger1 = logging.getLogger(handle)
logger2 = logging.getLogger(handle)
# logger1 and logger2 point to the same object:
# (logger1 is logger2) == True


# Convenient methods in order of verbosity from highest to lowest
logger.debug("this will get printed")
logger.info("this will get printed")
logger.warning("this will get printed")
logger.error("this will get printed")
logger.critical("this will get printed")


# In large applications where you would like more control over the logging,
# create sub-loggers from your main application logger.
component_logger = logger.getChild("component-a")
component_logger.info("this will get printed with the prefix `my-app.component-a`")

# If you wish to control the logging levels, you can set the level anywhere 
# in the hierarchy:
#
# - root
#   - my-app
#     - component-a
#

# Example for development:
logger.setLevel(logging.DEBUG)

# If that prints too much, enable debug printing only for your component:
component_logger.setLevel(logging.DEBUG)


# For production you rather want:
logger.setLevel(logging.WARNING)

混乱的一个常见根源是初始化错误的根记录器。考虑一下:

import logging
log = logging.getLogger("myapp")
log.warning("woot")
logging.basicConfig()
log.warning("woot")

输出:

woot
WARNING:myapp:woot

根据您的运行时环境和日志记录级别,第一条日志行(在基本配置之前)可能不会在任何地方显示


我的日志记录不起作用,因为它不生成任何输出文件。您是否看到我正在做的任何事情显然是错误的?logging.basicConfig( filename='logging.txt', level=logging.DEBUG) logger = logging.getLogger() logger.info('Test B') logging.info('Test A')
Rylan Schaeffer

甚至没有创建日志记录文件
Rylan Schaeffer,

我注意到,当我在其后放置一个断点时logger = logging.getLogger(),即使将级别指定为,该级别也设置为“警告” DEBUG。你知道我做错了吗?
Rylan Schaeffer

@RylanSchaeffer,您好,您可能想创建一个新问题并提供更多详细信息。这也将使其他人有机会帮助您。
Hubert Grzeskowiak

是的 通常,提出评论是找到答案的较快方法,因为至少有一个博学的人会看到我的问题
Rylan Schaeffer,

20

对于这里想要超级简单答案的任何人:只需设置要显示的级别即可。在我所有脚本的顶部,我只输入了:

import logging
logging.basicConfig(level = logging.INFO)

然后显示该级别或更高级别的任何内容:

logging.info("Hi you just set your fleeb to level plumbus")

它是由五个级别组成的层次结构,因此日志将以您设置的级别或更高级别显示。因此,如果要显示错误,可以使用logging.error("The plumbus is broken")

水平,在日益严重的依次是DEBUGINFOWARNINGERROR,和CRITICAL。默认设置为WARNING

这是一篇很好的文章,其中包含的信息比我的回答要好:https :
//www.digitalocean.com/community/tutorials/how-to-use-logging-in-python-3


14

也许试试这个?在我的情况下,删除所有处理程序后,似乎问题已解决。

for handler in logging.root.handlers[:]:
    logging.root.removeHandler(handler)

logging.basicConfig(filename='output.log', level=logging.INFO)

SyntaxError: invalid syntax
埃里克(Eric)

2
为什么这是必要的?python logger附带哪些处理程序,为什么要从那里开始呢?也许问题是,为什么basicConfig不覆盖它们/替换它们?
jrh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.