私はもともとこれを httpx を使用して見つけましたが、よりよく知られているリクエストにも適用されるため、例では後者を使用します。
ファイルを読み取ることによってちょうど間に合うようにバイトチャンクを作成するジェネレーターからデータが来ている場合、複数の要求を並行して行っています。カウンター/ロックを設定して同時リクエストの数を制限し、メモリに大量のデータが蓄積されないようにしました。完了したらヘッダーからいくつかのデータを取得する必要があるため、応答はリストに蓄積されます。
これは期待どおりには機能せず、リクエストが実行されるにつれてメモリ使用量が増加し続けているように見えました。これは、リクエストがリクエスト本文への参照を保持しているためであることがわかりました。これにより、参照カウントが 0 に達するのを防ぎ、データがガベージ コレクションされません。
最小限の再現可能な例:
import os
import sys
import requests
response = requests.put("https://httpbin.org/put", data=os.urandom(100000))
response.request.body # a bunch of bytes
sys.getrefcount(response.request.body) # I get 2
httpx の場合、参照は に保存されhttpx.Response.request.stream._body
ます。
応答を蓄積する前に要求への参照を削除することで問題を解決しましたが、これは予期されることですか? 追跡するのは非常に困難で、私が経験していたような意図しないメモリ リークが多く発生するように思えます。