Как отключить сообщения журнала из библиотеки запросов?

367

По умолчанию библиотека Python « Запросы» записывает сообщения журнала в консоль в соответствии с:

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

Меня обычно не интересуют эти сообщения, и я хотел бы отключить их. Как лучше всего замолчать эти сообщения или уменьшить многословность запросов?

aknuds1
источник
Связанный: nginx и gunicorn
Мартин Тома

Ответы:

574

Я узнал, как настроить уровень регистрации запросов , это делается через стандартный модуль регистрации . Я решил настроить его так, чтобы он не регистрировал сообщения, если они не являются хотя бы предупреждениями:

import logging

logging.getLogger("requests").setLevel(logging.WARNING)

Если вы хотите применить этот параметр и для библиотеки urllib3 (обычно используемой в запросах), добавьте следующее:

logging.getLogger("urllib3").setLevel(logging.WARNING)
aknuds1
источник
4
У меня та же проблема pysimplesoap, и этот ответ поможет мне спасти мой день
Джанит Чинтана
2
Вы можете объединить две строки следующим образом: logging.getLogger ('запросы'). SetLevel (logging.WARNING)
jpoppe
7
Мне пришлось добавить эту строку для регистратора "urllib3", чтобы подавить сообщения журнала запросов.
dgassaway
9
Мне нужно было импортировать логирование; logging.getLogger ("urllib3"). setLevel (logging.WARNING) тоже. Регистратор "запросов" не предотвращает эти сообщения.
m_messiah
4
По какой-то причине при использовании библиотеки запросов в python3 вы должны сделать, getLogger("urllib3")чтобы подавить сообщения.
Робру
104

Если вы пришли сюда в поисках способа изменить ведение журнала любого (возможно, глубоко вложенного) модуля, используйте 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 учтите, что этот метод показывает только те регистраторы, которые существуют на момент запуска приведенного выше фрагмента. Если, например, модуль создает новый регистратор при создании экземпляра класса, то вы должны поместить этот фрагмент после создания класса, чтобы напечатать его имя.

kbrose
источник
3
Спасибо, это помогло мне замолчать urllib3сообщения журнала при использовании boto3. Регистратор в таком случае есть botocore.vendored.requests.packages.urllib3, поэтому я использовал это: logging.getLogger("botocore.vendored.requests.packages.urllib3").setLevel(logging.WARNING)и я наконец избавился от сообщений.
Боб Дем
Большое спасибо за это! Изменение критериев печати позволило мне изолировать, что python -asticsearch был виновником в моем случае.
Роберт Таунли
2
Имейте в виду, что это не будет работать, когда модули создают свои регистраторы внутри своего класса, который вы будете вызывать позже, как это APSchedulerделает при вызове BackgroundScheduler.BackgroundScheduler().
user136036
@ user136036: объекты логгера являются одиночными, не имеет значения, если вы или библиотека создадите их в первую очередь. Если вы используете то же имя, что и библиотека, оно будет работать .
Мартин Питерс
1
Я думаю, что они говорят, что если вы перечислите регистраторы до того, как библиотека создаст свой регистратор, то они не будут перечислены. Что правильно.
kbrose
28
import logging
urllib3_logger = logging.getLogger('urllib3')
urllib3_logger.setLevel(logging.CRITICAL)

Таким образом, все сообщения уровня = INFO от urllib3 не будут присутствовать в файле журнала.

Таким образом, вы можете продолжать использовать level = INFO для ваших сообщений журнала ... просто измените это для библиотеки, которую вы используете.

Шаолинь
источник
4
Я предлагаю использовать setLevel(logging.WARNING)для регистрации также возможные предупреждения и сообщения об ошибках.
razz0
14

Позвольте мне скопировать / вставить раздел документации, который я написал неделю или две назад, после того, как у вас возникла проблема, похожая на вашу:

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')
Сорин
источник
Какой смысл быть более конкретным, чем просто «запросы» из практического POV?
aknuds1
Но что вы получаете, вызывая logging.getLogger ("запросы.packages.urllib3") вместо logging.getLogger ("запросы"), учитывая, что вы хотите повлиять на ведение журнала библиотеки запросов?
aknuds1
Вы имеете в виду, что вы хотите включить ведение журнала в запросах.packages.urllib3? Если это так, вы отвечаете не на тот вопрос.
aknuds1
@ aknuds1 Вам решать, хотите ли вы отключить или включить их, я только поместил код, который полностью контролирует это :)
sorin
3
Я думаю, что вы неправильно поняли суть вопроса.
aknuds1
14

Для любого, кто использует, logging.config.dictConfigвы можете изменить уровень журнала библиотеки запросов в словаре следующим образом:

'loggers': {
    '': {
        'handlers': ['file'],
        'level': level,
        'propagate': False
    },
    'requests.packages.urllib3': {
        'handlers': ['file'],
        'level': logging.WARNING
    }
}
TheHerk
источник
@SebastianWagner Django использует dictConfigпод капотом.
uhbif19
Спасибо огромное! Это довольно хорошо. Одно место, чтобы править всеми журналами библиотеки! :)
MehmedB
5

Установка имени логгера как requestsили requests.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
    },
Микко
источник
где эти уровни установлены?
Джавадба
У меня они есть в настройках Django, в base.py. Где их разместить, конечно, зависит от настроек вашего проекта.
Микко
2

Если у вас есть файл конфигурации, вы можете настроить его.

Добавьте urllib3 в раздел логгеров:

[loggers]
keys = root, urllib3

Добавьте раздел logger_urllib3:

[logger_urllib3]
level = WARNING
handlers =
qualname = requests.packages.urllib3.connectionpool
Санк
источник
Это совершенно правильный ответ для людей, которые используют файл конфигурации. Не уверен, почему так много голосов?
Патрик
1

Этот ответ здесь: Python: как подавить логирование операторов из сторонних библиотек?

Вы можете оставить уровень ведения журнала по умолчанию для 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")
Джеффри Ричи
источник
1
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
Мартин Тома
источник
0

Руководство Kbrose по поиску того, какой регистратор генерировал сообщения журнала, было чрезвычайно полезным. Для моего проекта Django мне пришлось перебирать 120 различных регистраторов, пока я не обнаружил, что именно elasticsearchбиблиотека Python вызывает у меня проблемы. Согласно руководству в большинстве вопросов, я отключил его, добавив это в мои регистраторы:

      ...
      'elasticsearch': {
          'handlers': ['console'],
          'level': logging.WARNING,
      },     
      ...

Публикация здесь на случай, если кто-то еще увидит бесполезные сообщения журнала, поступающие при выполнении запроса Elasticsearch.

Роберт Таунли
источник
-1

просто: просто добавь requests.packages.urllib3.disable_warnings()послеimport requests

evandrix
источник
2
Я не нашел этот метод в моей версии. Отключение предупреждений является чрезмерным, так как раздражающие сообщения являются уровнем INFO.
tripleee
-1

Я не уверен, что предыдущие подходы перестали работать, но в любом случае, вот еще один способ удаления предупреждений:

PYTHONWARNINGS="ignore:Unverified HTTPS request" ./do-insecure-request.py

По сути, добавление переменной среды в контексте выполнения скрипта.

Из документации: https://urllib3.readthedocs.org/en/latest/security.html#disabling-warnings

newlog
источник