私はHTTP通信用のpythonのリクエストモジュールを使用していて、すでに確立されているTCP接続を再利用する方法を知りたいですか?リクエストモジュールはステートレスであり、同じURLに対してgetを繰り返し呼び出すと、毎回新しい接続を作成しませんか?
ありがとう!!
要求モジュールはステートレスであり、同じURLに対してgetを繰り返し呼び出した場合、毎回新しい接続が作成されないのですか?
requests
モジュールはステートレスではありません。状態を無視し、必要に応じてグローバルシングルトン状態を効果的に使用できるようにします。*
そして、それ(または、むしろ、基礎となるライブラリの1つであるurllib3
)は、(ホスト名、ポート)のペアによってキー設定された接続プールを維持するため、通常、接続を魔法のように再利用できます。
ドキュメント が言うように:
すばらしいニュース— urllib3のおかげで、キープアライブはセッション内で100%自動です。セッション内で行ったリクエストは、適切な接続を自動的に再利用します!
すべての本文データが読み取られた後、接続は解放されて再利用のためにプールに戻されることに注意してください。必ず
stream
をFalse
に設定するか、content
オブジェクトのResponse
プロパティを読み取ってください。
では、「可能であれば」とはどういう意味ですか?上記のドキュメントが示すように、ストリーミング応答オブジェクトを存続させている場合、それらの接続は明らかに再利用できません。
また、接続プールは実際には無限ではなく有限のキャッシュであるため、大量の接続をスパム送信し、そのうちの2つが同じサーバーに対するものである場合は、常にしません頻繁に接続を再利用します。しかし、通常、それが実際に必要なことです。
*ここで関連する特定の状態は トランスポートアダプター です。各セッションはトランスポートアダプターを取得します。アダプタを手動で指定することも、グローバルデフォルトを指定することも、デフォルトのグローバルデフォルトを使用することもできます。これは、基本的にHTTP接続を管理するためのurllib3.PoolManager
をラップするだけです。詳細については、ドキュメントをご覧ください。
requests.get
やrequests.post
などのグローバル関数は、各呼び出しでrequests.Session
インスタンスを作成します。これらの関数で作成された接続は再利用できません。自動作成されたセッションにアクセスして、その後のリクエストでその接続プールを使用することができないためです。ほんの少しのリクエストを行う必要がある場合は、これらの関数を使用しても問題ありません。それ以外の場合は、自分でセッションを管理する必要があります。
以下は、グローバルrequests
関数とセッションを使用した場合のget
の動作の簡単な表示です。
準備、質問にはあまり関係ありません:
>>> import logging, requests, timeit
>>> logging.basicConfig(level=logging.DEBUG, format="%(message)s")
get
を呼び出すたびに新しい接続が確立されます。
>>> _ = requests.get("https://www.wikipedia.org")
Starting new HTTPS connection (1): www.wikipedia.org
>>> _ = requests.get("https://www.wikipedia.org")
Starting new HTTPS connection (1): www.wikipedia.org
ただし、後続の呼び出しに同じセッションを使用すると、接続は再利用されます。
>>> session = requests.Session()
>>> _ = session.get("https://www.wikipedia.org")
Starting new HTTPS connection (1): www.wikipedia.org
>>> _ = session.get("https://www.wikipedia.org")
>>> _ = session.get("https://www.wikipedia.org")
>>> _ = session.get("https://www.wikipedia.org")
パフォーマンス:
>>> timeit.timeit('_ = requests.get("https://www.wikipedia.org")', 'import requests', number=100)
Starting new HTTPS connection (1): www.wikipedia.org
Starting new HTTPS connection (1): www.wikipedia.org
Starting new HTTPS connection (1): www.wikipedia.org
...
Starting new HTTPS connection (1): www.wikipedia.org
Starting new HTTPS connection (1): www.wikipedia.org
Starting new HTTPS connection (1): www.wikipedia.org
52.74904417991638
>>> timeit.timeit('_ = session.get("https://www.wikipedia.org")', 'import requests; session = requests.Session()', number=100)
Starting new HTTPS connection (1): www.wikipedia.org
15.770191192626953
セッション(したがってセッションの接続プール)を再利用すると、はるかに高速に動作します。