どこからでも多くのWebページを取得するために、リクエストライブラリを使用しています。彼は適切なコードです:
response = requests.Session()
retries = Retry(total=5, backoff_factor=.1)
response.mount('http://', HTTPAdapter(max_retries=retries))
response = response.get(url)
しばらくすると、ページを取得している間、(同じWebページでは決して)ハング/フリーズします。中断したときのトレースバックは次のとおりです。
File "/Users/Student/Hockey/Scrape/html_pbp.py", line 21, in get_pbp
response = r.read().decode('utf-8')
File "/anaconda/lib/python3.6/http/client.py", line 456, in read
return self._readall_chunked()
File "/anaconda/lib/python3.6/http/client.py", line 566, in _readall_chunked
value.append(self._safe_read(chunk_left))
File "/anaconda/lib/python3.6/http/client.py", line 612, in _safe_read
chunk = self.fp.read(min(amt, MAXAMOUNT))
File "/anaconda/lib/python3.6/socket.py", line 586, in readinto
return self._sock.recv_into(b)
KeyboardInterrupt
誰かがそれを引き起こしている可能性があることを知っていますか?または、(より重要なことですが)再試行できるように、一定の時間がかかる場合にそれを停止する方法を誰かが知っていますか?
(読み取り) timeout を設定するように見えるかもしれません。
以下に沿ったもの:
response = response.get(url, timeout=5)
(これにより、接続タイムアウトと読み取りタイムアウトの両方が5秒に設定されます。)
requests
では、残念ながら、 docs で設定しても良いと言っていても、connectもreadタイムアウトもデフォルトでは設定されていません。それ:
外部サーバーへのほとんどのリクエストは、サーバーがタイムリーに応答しない場合に備えて、タイムアウトをアタッチする必要があります。デフォルトでは、タイムアウト値が明示的に設定されていない限り、リクエストはタイムアウトしません。タイムアウトがないと、コードは数分以上ハングする可能性があります。
完全を期すため、接続タイムアウトは、クライアントがリモートマシンへの接続を確立するのをrequests
が待機する秒数です。 read timeoutは、サーバーから送信されたバイト間でクライアントが待機する秒数です。
文書化された「送信」関数にパッチを適用すると、すべての要求に対してこれが修正されます-多くの依存ライブラリとSDKでも同様です。ライブラリにパッチを適用する場合は、サポートされている/ドキュメント化された関数にパッチを適用してください。パッチを適用しないと、パッチの効果が失われて静かに失われる可能性があります。
import requests
old_send = requests.Session.send
def new_send(*args, **kwargs):
if kwargs.get("timeout", None) is None:
kwargs["timeout"] = DEFAULT_TIMEOUT
return old_send(*args, **kwargs)
requests.Session.send = new_send
リクエストごとに指定する代わりに、タイムアウトをグローバルに設定するには:
from requests.adapters import TimeoutSauce
REQUESTS_TIMEOUT_SECONDS = float(os.getenv("REQUESTS_TIMEOUT_SECONDS", 5))
class CustomTimeout(TimeoutSauce):
def __init__(self, *args, **kwargs):
if kwargs["connect"] is None:
kwargs["connect"] = REQUESTS_TIMEOUT_SECONDS
if kwargs["read"] is None:
kwargs["read"] = REQUESTS_TIMEOUT_SECONDS
super().__init__(*args, **kwargs)
# Set it globally, instead of specifying ``timeout=..`` kwarg on each call.
requests.adapters.TimeoutSauce = CustomTimeout
sess = requests.Session()
sess.get(...)
sess.post(...)