0

我有一个使用 HTTP 连接下载数据的数据密集型Python脚本。我通常在一夜之间运行它。有时连接会失败,或者网站会暂时不可用。我有基本的错误处理,可以捕获这些异常并定期重试,在重试 5 分钟后优雅地退出(并记录错误)。

但是,我注意到有时工作会冻结。没有抛出错误,作业仍在运行,有时在最后一条打印消息后数小时。

最好的方法是:

  • 监控Python 脚本,
  • 检测它是否在给定时间间隔后无响应,
  • 如果它没有响应就退出它,
  • 开始另一个?

更新

感谢大家的帮助。正如你们中的一些人所指出的,urllibsocket模块没有正确设置超时。我将Python 2.5Freebaseurllib2模块一起使用,并捕获和处理MetawebErrorsurllib2.URLErrors。这是最后一个脚本挂起 12 小时后的错误输出示例:

  File "/home/matthew/dev/projects/myapp_module/project/app/myapp/contrib/freebase/api/session.py", line 369, in _httpreq_json
    resp, body = self._httpreq(*args, **kws)
  File "/home/matthew/dev/projects/myapp_module/project/app/myapp/contrib/freebase/api/session.py", line 355, in _httpreq
    return self._http_request(url, method, body, headers)
  File "/home/matthew/dev/projects/myapp_module/project/app/myapp/contrib/freebase/api/httpclients.py", line 33, in __call__
    resp = self.opener.open(req)
  File "/usr/lib/python2.5/urllib2.py", line 381, in open
    response = self._open(req, data)
  File "/usr/lib/python2.5/urllib2.py", line 399, in _open
    '_open', req)
  File "/usr/lib/python2.5/urllib2.py", line 360, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.5/urllib2.py", line 1107, in http_open
    return self.do_open(httplib.HTTPConnection, req)
  File "/usr/lib/python2.5/urllib2.py", line 1080, in do_open
    r = h.getresponse()
  File "/usr/lib/python2.5/httplib.py", line 928, in getresponse
    response.begin()
  File "/usr/lib/python2.5/httplib.py", line 385, in begin
    version, status, reason = self._read_status()
  File "/usr/lib/python2.5/httplib.py", line 343, in _read_status
    line = self.fp.readline()
  File "/usr/lib/python2.5/socket.py", line 372, in readline
    data = recv(1)
KeyboardInterrupt

您会注意到底部的套接字错误。由于我使用的是Python 2.5并且无法访问第三个urllib2.urlopen选项,是否有另一种方法可以监视和捕获此错误?例如,我正在捕获URLErrrrors - urllib2套接字中是否有另一种类型的错误,我可以捕获对我有帮助的?

4

4 回答 4

7

听起来您的脚本中存在错误。答案不是监控错误,而是寻找错误并修复它。

我们无法在不查看代码的情况下帮助您找到错误。但一般来说,您可能希望使用日志记录来查明问题发生的位置,并编写单元测试来帮助您建立对代码的哪些部分没有错误的信心。

另一个想法是用 Ctrl-C 打破“卡住”的程序并研究回溯消息。它将显示您的程序最后执行的行。这可能会为您提供脚本出错的线索。

于 2010-11-04T01:42:32.923 回答
4

由于该程序正在进行 Web 通信,因此我会启动一个调试代理,例如 Charles http://www.charlesproxy.com/,看看在您的脚本和服务器之间的来回切换中是否发生了任何奇怪的事情。

还要考虑套接字模块默认没有设置超时,因此可以挂起。但是,从 python 2.6 开始,您可以将第三个参数传递给 urllib2.urlopen(即如果您使用的是 urllib2),以秒为单位指定请求超时时间。这样脚本就会出错,而不是紧张地等待来自可能不合作的服务器的响应。如果您还没有,我会先检查这些东西,然后再尝试更详细的操作。

python 2.5 更新: 要在 python < 2.6 中执行此操作,您必须直接在 urllib2 使用的套接字模块中设置超时值。我还没有尝试过,但它可能有效。在http://www.voidspace.org.uk/python/articles/urllib2.shtml找到此信息:

import socket
import urllib2

# timeout in seconds
timeout = 10
socket.setdefaulttimeout(timeout)

# this call to urllib2.urlopen now uses the default timeout
# we have set in the socket module
req = urllib2.Request('http://www.voidspace.org.uk')
response = urllib2.urlopen(req)
于 2010-11-04T02:25:49.120 回答
1

一个简单的方法来做你的要求是利用你当前程序发送的UDP数据包到另一个监控输出的收集程序。如果它在一定时间内没有收到数据包,它会杀死另一个 python 进程然后重新启动另一个

于 2010-11-04T01:41:53.247 回答
1

当您怀疑它被冻结时,您可以运行您的脚本pdb并闯入。它不会单独工作,但可能会帮助您弄清楚它为什么会冻结。

于 2010-11-04T01:45:23.140 回答