我在 python 中构建一个下载管理器是为了好玩,有时与服务器的连接仍然存在,但服务器没有向我发送数据,所以读取方法(HTTPResponse)永远阻止我。例如,当我从位于我所在国家/地区以外的服务器下载时,就会发生这种情况,这限制了其他国家/地区的带宽。
如何为读取方法设置超时(例如 2 分钟)?
谢谢,尼尔。
我在 python 中构建一个下载管理器是为了好玩,有时与服务器的连接仍然存在,但服务器没有向我发送数据,所以读取方法(HTTPResponse)永远阻止我。例如,当我从位于我所在国家/地区以外的服务器下载时,就会发生这种情况,这限制了其他国家/地区的带宽。
如何为读取方法设置超时(例如 2 分钟)?
谢谢,尼尔。
如果您卡在某个 Python 版本上< 2.6
,一种(不完美但可用)的方法是
import socket
socket.setdefaulttimeout(10.0) # or whatever
在你开始使用之前httplib
。文档在此处,并明确说明setdefaulttimeout
自 Python 2.3 起可用 - 从您执行此调用到再次调用同一函数时创建的每个套接字都将使用 10 秒的超时。如果要保存以前的超时(包括无),可以在设置新超时之前使用getdefaulttimeoutsetdefaulttimeout
以便以后可以恢复它(使用另一个)。
当你需要使用一些旧的高级库时,这些函数和习语非常有用,这些库使用 Python socket
s 但没有给你一个设置超时的好方法(当然最好使用更新的高级库,例如httplib
版本httplib2
在这种情况下,2.6 或第三方附带,但这并不总是可行的,使用默认超时设置可能是一个很好的解决方法)。
您必须在HTTPConnection初始化期间设置它。
注意:如果你使用的是旧版本的 Python,那么你可以安装httplib2;许多人认为它是 httplib 的更好替代品,并且确实支持timeout。
不过,我从未使用过它,我只是在报告文档和博客所说的内容。
如果下载很大,设置默认超时可能会提前中止下载,而不是仅在它停止接收超时值的数据时中止。HTTPlib2 可能是要走的路。
5年后,但希望这会帮助别人......
我正在破坏我的大脑试图弄清楚这一点。我的问题是服务器返回损坏的内容,因此返回的数据比它想象的要少。
我想出了一个似乎工作正常的讨厌的解决方案。它是这样的:
# NOTE I directly disabling blocking is not necessary but it represents
# an important piece to the problem so I am leaving it here.
# http_response.fp._sock.socket.setblocking(0)
http_response.fp._sock.settimeout(read_timeout)
http_response.read(chunk_size)
注意此解决方案也适用于python 请求 任何实现普通 python 套接字的库(应该是全部?)。你只需要更深入几个层次:
resp.raw._fp.fp._sock.socket.setblocking()
resp.raw._fp.fp._sock.settimeout(read_timeout)
resp.raw.read(chunk_size)
在撰写本文时,我还没有尝试过以下方法,但理论上它应该可以工作:
resp = requests.get(some_url, stream=True)
resp.raw._fp.fp._sock.socket.setblocking()
resp.raw._fp.fp._sock.settimeout(read_timeout)
for chunk in resp.iter_content(chunk_size):
# do stuff
解释
我在阅读这个 SO question for setting a timeout on socket.recv时偶然发现了这种方法
归根结底,任何 http 请求都有一个套接字。对于套接字位于的 httplib resp.raw._fp.fp._sock.socket
。这resp.raw._fp.fp._sock
是一个socket._fileobj
(老实说,我并没有深入研究),我想它的settimeout
方法在内部将它设置在socket
属性上。