在python中将超时设置为http响应读取方法

set timeout to http response read method in python

为了好玩,我在python中构建了一个下载管理器,有时到服务器的连接仍在运行,但服务器不向我发送数据,所以read方法(httpresponse)永远阻止我。例如,当我从位于我的国家之外的服务器下载时,会发生这种情况,这会限制到其他国家的带宽。

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

谢谢,Nir。


如果您坚持使用某些Python版本的< 2.6,那么可以使用一种(不完美但可用的)方法

1
2
import socket
socket.setdefaulttimeout(10.0)  # or whatever

在开始使用httplib之前。文档在这里,并且清楚地声明,自从python 2.3以来,setdefaulttimeout是可用的——从您执行此调用到您再次调用同一个函数的每个套接字都将使用10秒的超时。如果要保存以前的超时(包括无超时),以便以后可以恢复它(使用另一个setdefaulttimeout),则可以在设置新的超时之前使用getdefaulttimeout。

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


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

注意:如果您使用的是旧版本的python,那么您可以安装httplib2;许多人认为它是httplib的一个更好的替代方案,并且它支持超时。不过,我从未使用过它,我只是在报告文档和博客的内容。


如果下载量很大,设置默认超时可能会提前中止下载,而不是仅当它停止接收超时值的数据时才中止下载。httplib2可能是未来的发展方向。


5年后,但希望这能帮助其他人…

我在绞尽脑汁想弄清楚。我的问题是服务器返回了损坏的内容,因此返回的数据比它想象的要少。

我想出了一个令人讨厌的解决方案,似乎工作正常。这就是:

1
2
3
4
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请求any library that implements the normal python sockets(which should be all of them?)。.你只需要更深入一些:

1
2
3
resp.raw._fp.fp._sock.socket.setblocking()
resp.raw._fp.fp._sock.settimeout(read_timeout)
resp.raw.read(chunk_size)

就这篇文章而言,我没有尝试过以下方法,但理论上它是可行的:

1
2
3
4
5
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

解释

我在阅读这个问题时偶然发现了这种方法,即设置socket.recv的超时。

一天结束时,任何HTTP请求都有一个套接字。对于httplib,套接字位于resp.raw._fp.fp._sock.socketresp.raw._fp.fp._sock是一个socket._fileobj(老实说,我并没有深入研究过),我认为它是settimeout方法,内部将它设置在socket属性上。