【问题标题】:urlopen freezes at random, timout is ignoredurlopen 随机冻结,超时被忽略
【发布时间】:2013-06-22 10:09:35
【问题描述】:

我有一个连接到 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 freezes script infinitely even though timeout is set, How can I force urllib2 to time out?, Timing out urllib2 urlopen operation in Python 2.4, Timeout function if it takes too long to finish )

但是没有任何效果。我的印象是线程在 urlopen 执行某些操作时冻结,完成后它解冻,然后所有计时器和超时返回 w 超时错误。但执行时间仍然超过 5s。

我发现this 旧邮件列表关于 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 接受浮点数。

【问题讨论】:

    标签: python timeout urllib2


    【解决方案1】:

    查看源代码,timeout 值实际上是 Python 在从远程主机接收数据包之间等待的最长时间。

    因此,如果您将超时设置为 2 秒,并且远程主机以每秒一个数据包的速率发送 60 个数据包,则永远不会发生超时,尽管整个过程仍需要 60 秒。

    由于urlopen() 函数在远程主机发送完所有 HTTP 标头后才会返回,因此如果它发送标头的速度非常慢,您无能为力。

    如果您需要总体时间限制,您可能必须使用非阻塞 I/O 实现自己的 HTTP 客户端。

    【讨论】:

    • 完美答案。谢谢你。即使我觉得应该有一个整体超时可用。如果我按照建议实现自定义 HTTP 客户端,我会更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多