我有一个连接到 URL 并获取一些 json 的 API 管理器。很简单。从方法上截取:
req = Request(url)
socket.setdefaulttimeout(timeout)
resp = urlopen(req, None, timeout)
data = resp.read()
resp.close()
它在大多数情况下都能正常工作,但在随机时间间隔内,完成请求需要 5 秒。即使超时设置为 0.5 或 1.0 或其他任何值。我已经非常仔细地记录了它,所以我 100% 确定需要时间的行是数字 #3(即 resp = urlopen(req, None, timeout))。
我已经尝试了我在超时装饰器和计时器等主题上找到的所有解决方案。(列出其中一些: Python urllib2.urlopen 即使设置了超时也会无限冻结脚本, 如何强制 urllib2 超时?,超时 urllib2 urlopen Python 2.4 中的操作,如果完成时间过长,则使用超时功能 )
但没有任何效果。我的印象是线程在 urlopen 执行某些操作时冻结,完成后它解冻,然后所有计时器和超时返回 w 超时错误。但执行时间仍然超过 5s。
我找到了这个关于 urllib2 和分块编码处理的旧邮件列表。因此,如果问题仍然存在,那么解决方案可能是基于 httplib.HTTP 而不是 httplib.HTTPConnection 编写自定义 urlopen。另一种可能的解决方案是尝试一些多线程魔法......
这两种解决方案似乎都具有侵略性。让我感到困扰的是,超时并没有一直起作用。
脚本的执行时间不超过0.5s非常重要。任何人都知道我为什么会经历冻结或者可能是一种帮助我的方法吗?
根据接受的答案更新: 我改变了方法并改用 curl 。与 unix timeout 一起,它可以按我的意愿工作。示例代码如下:
t_timeout = str(API_TIMEOUT_TIME)
c_timeout = str(CURL_TIMEOUT_TIME)
cmd = ['timeout', t_timeout, 'curl', '--max-time', c_timeout, url]
prc = Popen(cmd, stdout=PIPE, stderr=PIPE)
response = prc.communicate()
由于 curl 只接受 int 作为超时,我添加了超时。timeout 接受浮点数。