web-dev-qa-db-ja.com

python-requestsモジュールからのすべてのリクエストを記録します

python Requests を使用しています。 OAuthアクティビティをデバッグする必要があります。そのため、実行中のすべてのリクエストをログに記録したいと思います。 ngrepでこの情報を取得できましたが、残念ながらhttps接続(OAuthに必要)をgrepすることはできません。

RequestsがアクセスしているすべてのURL(+パラメーター)のログを有効にするにはどうすればよいですか?

72
dangonfast

基礎となるurllib3ライブラリは、 logging module ですべての新しい接続とURLを記録しますが、POSTボディは記録しません。 GETリクエストの場合、これで十分です:

import logging

logging.basicConfig(level=logging.DEBUG)

最も詳細なログオプションが提供されます。ロギングレベルと宛先を設定する方法の詳細については、 logging HOWTO を参照してください。

短いデモ:

>>> import requests
>>> import logging
>>> logging.basicConfig(level=logging.DEBUG)
>>> r = requests.get('http://httpbin.org/get?foo=bar&baz=python')
INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): httpbin.org
DEBUG:requests.packages.urllib3.connectionpool:"GET /get?foo=bar&baz=python HTTP/1.1" 200 353

次のメッセージが記録されます。

  • INFO:新しい接続(HTTPまたはHTTPS)
  • INFO:接続のドロップ
  • INFO:リダイレクト
  • WARN:接続プールがいっぱいです(これが頻繁に発生すると、接続プールのサイズが大きくなります)
  • WARN:接続の再試行
  • DEBUG:接続の詳細:メソッド、パス、HTTPバージョン、ステータスコード、応答の長さ
66
Martijn Pieters

httplibレベル(requestsurllib3httplib)でデバッグを有効にする必要があります。

両方を切り替える(..._on()..._off())、または一時的にオンにするいくつかの関数を次に示します。

import logging
import contextlib
try:
    from http.client import HTTPConnection # py3
except ImportError:
    from httplib import HTTPConnection # py2

def debug_requests_on():
    '''Switches on logging of the requests module.'''
    HTTPConnection.debuglevel = 1

    logging.basicConfig()
    logging.getLogger().setLevel(logging.DEBUG)
    requests_log = logging.getLogger("requests.packages.urllib3")
    requests_log.setLevel(logging.DEBUG)
    requests_log.propagate = True

def debug_requests_off():
    '''Switches off logging of the requests module, might be some side-effects'''
    HTTPConnection.debuglevel = 0

    root_logger = logging.getLogger()
    root_logger.setLevel(logging.WARNING)
    root_logger.handlers = []
    requests_log = logging.getLogger("requests.packages.urllib3")
    requests_log.setLevel(logging.WARNING)
    requests_log.propagate = False

@contextlib.contextmanager
def debug_requests():
    '''Use with 'with'!'''
    debug_requests_on()
    yield
    debug_requests_off()

デモの使用:

>>> requests.get('http://httpbin.org/')
<Response [200]>

>>> debug_requests_on()
>>> requests.get('http://httpbin.org/')
INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): httpbin.org
DEBUG:requests.packages.urllib3.connectionpool:"GET / HTTP/1.1" 200 12150
send: 'GET / HTTP/1.1\r\nHost: httpbin.org\r\nConnection: keep-alive\r\nAccept-
Encoding: gzip, deflate\r\nAccept: */*\r\nUser-Agent: python-requests/2.11.1\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
header: Server: nginx
...
<Response [200]>

>>> debug_requests_off()
>>> requests.get('http://httpbin.org/')
<Response [200]>

>>> with debug_requests():
...     requests.get('http://httpbin.org/')
INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): httpbin.org
...
<Response [200]>

HEADERSとDATAを含むREQUESTと、HEADERSがあるがDATAがないRESPONSEが表示されます。不足しているのは、記録されないresponse.bodyのみです。

ソース

97
Yohann

python 3+を使用している場合

import requests
import logging
import http.client

http.client.HTTPConnection.debuglevel = 1

logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
35
forrestj

私はpython 3.4を使用しています、リクエスト2.19.1:

「urllib3」は、現在取得するロガーです(「requests.packages.urllib3」ではなくなりました)。基本的なログは、http.client.HTTPConnection.debuglevelを設定しなくても発生します

2
Mike Smith

Pythonロギングシステム(import logging)を取得して低レベルのデバッグログメッセージを送信しようとすると、次のことを発見して驚きました。

requests --> urllib3 --> http.client.HTTPConnection

urlb3のみが実際にPython loggingシステムを使用すること:

  • requestsno
  • http.client.HTTPConnectionno
  • urllib3yes

もちろん、以下を設定することでHTTPConnectionからデバッグメッセージを抽出できます。

HTTPConnection.debuglevel = 1

しかし、これらの出力はprintステートメントを介して単に出力されます。これを証明するには、単にPython 3.7 client.pyソースコードをgrepし、自分でprintステートメントを表示します(@Yohannに感謝)。

curl https://raw.githubusercontent.com/python/cpython/3.7/Lib/http/client.py |grep -A1 debuglevel` 

おそらく、標準出力を何らかの方法でリダイレクトすると、靴べらの標準出力をロギングシステムに取り込み、強力にキャプチャすることができます。ログファイル。

urlib3」ではなく「requests.packages.urllib3」ロガーを選択します

Python 3 loggingシステムを介してurlib3デバッグ情報をキャプチャするには、インターネット上の多くのアドバイスに反して、@ MikeSmithが指摘するように、インターセプトする運はあまりありません。

log = logging.getLogger('requests.packages.urllib3')

代わりに以下を行う必要があります。

log = logging.getLogger('urllib3')

url3libをログファイルにデバッグする

Python loggingシステムを使用してurl3lib作業をログファイルに記録するコードを次に示します。

import requests
import logging
from http.client import HTTPConnection  # py3

# log = logging.getLogger('requests.packages.urllib3')  # useless
log = logging.getLogger('urllib3')  # works

log.setLevel(logging.DEBUG)  # needed
fh = logging.FileHandler("requests.log")
log.addHandler(fh)

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

結果:

Starting new HTTP connection (1): httpbin.org:80
http://httpbin.org:80 "GET / HTTP/1.1" 200 3168

HTTPConnection.debuglevel print()ステートメントの有効化

HTTPConnection.debuglevel = 1を設定した場合

from http.client import HTTPConnection  # py3
HTTPConnection.debuglevel = 1
requests.get('http://httpbin.org/')

追加のジューシーな低レベル情報のprintステートメント出力が得られます。

send: b'GET / HTTP/1.1\r\nHost: httpbin.org\r\nUser-Agent: python- 
requests/2.22.0\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
header: Access-Control-Allow-Credentials header: Access-Control-Allow-Origin 
header: Content-Encoding header: Content-Type header: Date header: ...

この出力はPython printシステムではなくloggingを使用するため、従来のloggingストリームまたはファイルハンドラーを使用してキャプチャすることはできません(ただし、 stdout)のリダイレクトによるファイル。

上記の2つを組み合わせます-コンソールへのすべての可能なロギングを最大化します

可能なすべてのロギングを最大化するには、以下を使用してコンソール/ stdout出力を解決する必要があります。

import requests
import logging
from http.client import HTTPConnection  # py3

log = logging.getLogger('urllib3')
log.setLevel(logging.DEBUG)

# logging from urllib3 to console
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
log.addHandler(ch)

# print statements from `http.client.HTTPConnection` to console/stdout
HTTPConnection.debuglevel = 1

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

出力の全範囲を与える:

Starting new HTTP connection (1): httpbin.org:80
send: b'GET / HTTP/1.1\r\nHost: httpbin.org\r\nUser-Agent: python-requests/2.22.0\r\nAccept-Encoding: gzip, deflate\r\nAccept: */*\r\nConnection: keep-alive\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
http://httpbin.org:80 "GET / HTTP/1.1" 200 3168
header: Access-Control-Allow-Credentials header: Access-Control-Allow-Origin 
header: Content-Encoding header: ...
2
abulka