Python urllib2.urlopen 设置超时后仍无限冻结脚本

3 投票
2 回答
6306 浏览
提问于 2025-04-17 05:59

函数 urllib2.urlopen 会卡住。所以我有几个简单的问题:

  • 为什么即使设置了超时,urlopen 还是会让我的脚本永远卡住?
  • 我该如何访问一个网址的数据(在这个例子中是:http://api.own3d.tv/live?channel=FnaticTV),而不让我的 Python 程序永远卡住?

这是卡住的部分(在 own3d.py 中):

# Try three times to make contact
while True:
    try:
        # Connect to API 

        # Right here! It freezes here
        connection = urllib2.urlopen(request, timeout=10)

        xmlstring = connection.read() 
    except URLError as e:
        tries += 1
        if tries >= 3:
            sys.stderr.write(
                      'own3dStreamsUpdater: Fatal error: Repeated timeouts')
            exit()

这是我按下键盘中断后得到的堆栈跟踪信息

Traceback (most recent call last):
  File "", line 1, in 
  File "honsapp/own3dStreamsUpdater.py", line 53, in updateStreamInfo
    streamInfo = getStreamInfo(stream)
  File "honsapp/own3d.py", line 98, in getStreamInfo
    connection = urllib2.urlopen(request, timeout=10)
  File "/usr/local/lib/python2.7/urllib2.py", line 126, in urlopen
    return _opener.open(url, data, timeout)
  File "/usr/local/lib/python2.7/urllib2.py", line 394, in open
    response = self._open(req, data)
  File "/usr/local/lib/python2.7/urllib2.py", line 412, in _open
    '_open', req)
  File "/usr/local/lib/python2.7/urllib2.py", line 372, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python2.7/urllib2.py", line 1199, in http_open
    return self.do_open(httplib.HTTPConnection, req)
  File "/usr/local/lib/python2.7/urllib2.py", line 1170, in do_open
    r = h.getresponse(buffering=True)
  File "/usr/local/lib/python2.7/httplib.py", line 1027, in getresponse
    response.begin()
  File "/usr/local/lib/python2.7/httplib.py", line 407, in begin
    version, status, reason = self._read_status()
  File "/usr/local/lib/python2.7/httplib.py", line 365, in _read_status
    line = self.fp.readline()
  File "/usr/local/lib/python2.7/socket.py", line 447, in readline
    data = self._sock.recv(self._rbufsize)
KeyboardInterrupt

编辑

我让我的脚本运行了一整夜。我不知道具体花了多长时间(不过超过五分钟),但最后脚本终于放弃了,并给了我一个堆栈跟踪:

Traceback (most recent call last):
  File "honsapp/own3dStreamsUpdater.py", line 260, in 
    newInfo()
  File "honsapp/own3dStreamsUpdater.py", line 172, in newInfo
    result = updateStreamInfo(stream)
  File "honsapp/own3dStreamsUpdater.py", line 53, in updateStreamInfo
    streamInfo = getStreamInfo(stream)
  File "/root/Dropbox/Projects/honstreams/honsapp/own3d.py", line 98, in getStreamInfo
    connection = urllib2.urlopen(request, timeout=10)
  File "/usr/local/lib/python2.7/urllib2.py", line 126, in urlopen
    return _opener.open(url, data, timeout)
  File "/usr/local/lib/python2.7/urllib2.py", line 394, in open
    response = self._open(req, data)
  File "/usr/local/lib/python2.7/urllib2.py", line 412, in _open
    '_open', req)
  File "/usr/local/lib/python2.7/urllib2.py", line 372, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python2.7/urllib2.py", line 1199, in http_open
    return self.do_open(httplib.HTTPConnection, req)
  File "/usr/local/lib/python2.7/urllib2.py", line 1170, in do_open
    r = h.getresponse(buffering=True)
  File "/usr/local/lib/python2.7/httplib.py", line 1027, in getresponse
    response.begin()
  File "/usr/local/lib/python2.7/httplib.py", line 407, in begin
    version, status, reason = self._read_status()
  File "/usr/local/lib/python2.7/httplib.py", line 371, in _read_status
    raise BadStatusLine(line)
httplib.BadStatusLine: ''

2 个回答

4

你确定urlopen()这个调用会卡住吗?因为如果这个调用成功的话,你的while循环是不会结束的。

5

这个脚本根本不会卡住,但它很好地说明了为什么你不应该在疲惫的时候写代码。原本应该尝试连接API三次的循环会一直运行下去,因为我忘记在里面加一个break语句。

这个问题真是太傻了,我不会怪你把它删掉。

修复后的代码:

# Try three times to make contact
while True:
    try:
        # Connect to API 
        connection = urllib2.urlopen(request, timeout=10)
        xmlstring = connection.read()
        break
    except URLError as e:
        tries += 1
        if tries >= 3:
            sys.stderr.write(
                      'own3dStreamsUpdater: Fatal error: Repeated timeouts')
            exit()

撰写回答