1

我在 python 中构建一个下载管理器是为了好玩,有时与服务器的连接仍然存在,但服务器没有向我发送数据,所以读取方法(HTTPResponse)永远阻止我。例如,当我从位于我所在国家/地区以外的服务器下载时,就会发生这种情况,这限制了其他国家/地区的带宽。

如何为读取方法设置超时(例如 2 分钟)?

谢谢,尼尔。

4

4 回答 4

3

如果您卡在某个 Python 版本上< 2.6,一种(不完美但可用)的方法是

import socket
socket.setdefaulttimeout(10.0)  # or whatever

在你开始使用之前httplib。文档在此处,并明确说明setdefaulttimeout自 Python 2.3 起可用 - 从您执行此调用到再次调用同一函数时创建的每个套接字都将使用 10 秒的超时。如果要保存以前的超时(包括无),可以在设置新超时之前使用getdefaulttimeoutsetdefaulttimeout以便以后可以恢复它(使用另一个)。

当你需要使用一些旧的高级库时,这些函数和习语非常有用,这些库使用 Python sockets 但没有给你一个设置超时的好方法(当然最好使用更新的高级库,例如httplib版本httplib2在这种情况下,2.6 或第三方附带,但这并不总是可行的,使用默认超时设置可能是一个很好的解决方法)。

于 2010-04-04T00:27:51.087 回答
2

您必须在HTTPConnection初始化期间设置它。

注意:如果你使用的是旧版本的 Python,那么你可以安装httplib2;许多人认为它是 httplib 的更好替代品,并且确实支持timeout
不过,我从未使用过它,我只是在报告文档和博客所说的内容。

于 2010-04-03T23:37:16.103 回答
1

如果下载很大,设置默认超时可能会提前中止下载,而不是仅在它停止接收超时值的数据时中止。HTTPlib2 可能是要走的路。

于 2010-08-30T18:02:49.500 回答
-1

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属性上。

于 2015-12-03T06:50:09.430 回答