我该如何禁用Requests库中的日志消息?

443

默认情况下,Requests Python库会将日志消息写入控制台,例如:

Starting new HTTP connection (1): example.com
http://example.com:80 "GET / HTTP/1.1" 200 606

我通常对这些消息不感兴趣,希望能够禁用它们。有什么最好的方法可以使这些消息静音或减少请求的冗长程度?


相关内容:nginx 和 gunicorn - Martin Thoma
13个回答

711

我发现如何配置requests的日志级别,它是通过标准的logging模块完成的。我决定将其配置为仅在消息至少为警告级别时才记录日志:

import logging

logging.getLogger("requests").setLevel(logging.WARNING)
如果您希望将此设置应用于urllib3库(通常由requests使用),请添加以下内容:
logging.getLogger("urllib3").setLevel(logging.WARNING)

5
我与“pysimplesoap”遇到了同样的问题,这个答案帮助我挽回了我的一天。 - Janith Chinthana
8
我需要添加这一行代码来禁止“urllib3”记录器输出请求日志信息。 - dgassaway
13
我需要导入日志记录模块:logging; 并且也需要设置"urllib3"的日志级别为WARNING。不过,针对"requests"的日志记录器并不能阻止这些信息的输出。 - m_messiah
6
在使用Python3中的requests库时,出于某种原因,您需要执行getLogger("urllib3")来抑制消息。 - robru
7
当前版本的 requests 库不再集成 urllib3,因此不再记录任何日志。你只需要让 urllib3 库停止传递日志信息:logging.getLogger("urllib3").propagate = False,或者如果你仍然需要查看警告或关键信息(当前只发出警告),则可以提高日志级别。 - Martijn Pieters
显示剩余7条评论

137

如果您在这里寻找修改任何(可能是深度嵌套的)模块的日志记录方式的方法,请使用logging.Logger.manager.loggerDict获取所有日志记录器对象的字典。返回的名称可以用作logging.getLogger的参数:

import requests
import logging
for key in logging.Logger.manager.loggerDict:
    print(key)
# requests.packages.urllib3.connectionpool
# requests.packages.urllib3.util
# requests.packages
# requests.packages.urllib3
# requests.packages.urllib3.util.retry
# PYREADLINE
# requests
# requests.packages.urllib3.poolmanager

logging.getLogger('requests').setLevel(logging.CRITICAL)
# Could also use the dictionary directly:
# logging.Logger.manager.loggerDict['requests'].setLevel(logging.CRITICAL)

根据用户user136036的评论,需要注意该方法仅显示您运行上述片段时存在的记录器。例如,如果模块在实例化类时创建新的记录器,则必须在创建类之后放置此片段才能打印其名称。


3
谢谢,这篇文章帮助我在使用boto3时消除了urllib3的日志信息。在这种情况下,记录器是botocore.vendored.requests.packages.urllib3,因此我使用了以下代码:logging.getLogger("botocore.vendored.requests.packages.urllib3").setLevel(logging.WARNING),最终成功摆脱了这些信息。 - Bob Dem
2
请注意,当模块在稍后调用时在其类内部创建其记录器(例如APScheduler在调用BackgroundScheduler.BackgroundScheduler()时)时,此方法将无法正常工作。 - user136036
1
@user136036:日志对象是单例的,无论你还是库先创建它们都没关系。如果你使用与库使用完全相同的名称,它将正常工作 - Martijn Pieters
2
我认为他们的意思是如果在库创建其记录器之前列出记录器,则不会将其列出。这是正确的。 - kbrose
这帮助我找到了写有请求信息的日志消息并想要摆脱的模块(azure)。非常感谢! - stinodego
显示剩余2条评论

32
import logging
urllib3_logger = logging.getLogger('urllib3')
urllib3_logger.setLevel(logging.CRITICAL)

通过这种方式,来自urllib3的级别为INFO的所有消息都不会出现在日志文件中。

因此,您仍然可以继续使用level = INFO记录消息...只需修改您正在使用的库的级别即可。


4
我建议使用setLevel(logging.WARNING)来记录可能的警告和错误信息。 - Mikko Koho

29
import logging

# Only show warnings
logging.getLogger("urllib3").setLevel(logging.WARNING)

# Disable all child loggers of urllib3, e.g. urllib3.connectionpool
logging.getLogger("urllib3").propagate = False

19

如果有人使用logging.config.dictConfig,您可以像这样在字典中更改请求库的日志级别:

'loggers': {
    '': {
        'handlers': ['file'],
        'level': level,
        'propagate': False
    },
    'requests.packages.urllib3': {
        'handlers': ['file'],
        'level': logging.WARNING
    }
}

Django在内部使用dictConfig - uhbif19
非常感谢!这很不错。一个地方管理所有的库日志!! :) - MehmedB

15

让我复制/粘贴文档部分,它是我大约一两周前写的,在遇到与您类似的问题后:

import requests
import logging

# these two lines enable debugging at httplib level (requests->urllib3->httplib)
# you will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA.
# the only thing missing will be the response.body which is not logged.
import httplib
httplib.HTTPConnection.debuglevel = 1

logging.basicConfig() # you need to initialize logging, otherwise you will not see anything from requests
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True

requests.get('http://httpbin.org/headers')

从实际角度来看,比仅使用“请求”更具体的意义何在? - aknuds1
但是,如果您想影响请求库的日志记录,与调用logging.getLogger("requests")相比,通过调用logging.getLogger("requests.packages.urllib3")会获得什么好处呢? - aknuds1
1
你的意思是希望在requests.packages.urllib3中启用日志记录吗?如果是这样,那么你回答错了问题。 - aknuds1
@aknuds1 这取决于您是否要禁用或启用它们,我只提供了完全控制此操作的代码 :) - sorin
4
我觉得你误解了问题的范围。 - aknuds1

8

将记录器名称设置为requestsrequests.urllib3对我没有起作用。我必须指定确切的记录器名称来更改记录级别。

首先查看您定义了哪些记录器,以确定您想要删除哪些记录器。

print(logging.Logger.manager.loggerDict)

您将看到以下内容:

{...'urllib3.poolmanager': <logging.Logger object at 0x1070a6e10>, 'django.request': <logging.Logger object at 0x106d61290>, 'django.template': <logging.Logger object at 0x10630dcd0>, 'django.server': <logging.Logger object at 0x106dd6a50>, 'urllib3.connection': <logging.Logger object at 0x10710a350>,'urllib3.connectionpool': <logging.Logger object at 0x106e09690> ...}

然后为确切的记录器配置级别:

   'loggers': {
    '': {
        'handlers': ['default'],
        'level': 'DEBUG',
        'propagate': True
    },
    'urllib3.connectionpool': {
        'handlers': ['default'],
        'level': 'WARNING',
        'propagate' : False
    },

这些级别在哪里设置? - WestCoastProjects
我将它们放在Django设置中的base.py文件中。当然,放置它们的位置取决于您的项目设置。 - Mikko

5
如果您有配置文件,可以进行配置。
在日志记录器部分添加urllib3:
[loggers]
keys = root, urllib3

添加logger_urllib3部分:

[logger_urllib3]
level = WARNING
handlers =
qualname = requests.packages.urllib3.connectionpool

1
对于使用配置文件的人来说,这是一个完全有效的答案。不确定为什么它会有那么多负评? - Patrick

4
这个答案在这里:Python: how to suppress logging statements from third party libraries? 你可以保留basicConfig的默认日志级别,然后在获取模块的记录器时设置为DEBUG级别。
logging.basicConfig(format='%(asctime)s %(module)s %(filename)s:%(lineno)s - %(message)s')
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

logger.debug("my debug message")

0

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