使用Python urllib2.urlopen检测挂起情况

13 投票
1 回答
4372 浏览
提问于 2025-04-16 15:12

我正在使用Python的urllib2来发送一个HTTP POST请求:

import socket, urllib, urllib2

socket.setdefaulttimeout(15)    

postdata = urllib.urlencode({'value1' : 'a string', 'value2' : 'another string'})
headers = {
    'User-Agent': 'Agent',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Accept': 'text/html, */*',
}

try: 
    request = urllib2.Request('http://www.example.com', postData, headers)
    response = urllib2.urlopen(request)
except urllib2.HTTPError, e:
    # Handle here
except urllib2.URLError, e:
    # Handle here
except httplib.HTTPException, e:
    # Handle here

有时候,网络问题会导致urlopen这个调用一直没有返回。我们看到其他错误(包括超时)都能被except块正确处理,并且我们也调用了socket.setdefaulttimeout(),但仍然有一些情况下urlopen就是不会返回。

我知道它没有返回是因为我们在实际代码中有一些日志记录,在问题发生时,只有之前的日志被记录,而之后的日志完全没有,这样脚本就会一直卡在那里。

有什么好的方法来检测或处理这个问题吗?

1 个回答

10

你可以使用信号,首先为你的信号设置一个处理器

import signal
...
def handler(signum, frame):
    print 'Signal handler called with signal', signum
...
signal.signal(signal.SIGALRM, handler)

然后在调用 urlopen 之前设置一个闹钟

signal.alarm(5)
response = urllib2.urlopen(request)
signal.alarm(0) # Disable the signal

如果在5秒后(或者你想要的时间)闹钟没有被关闭,操作系统会调用你设置的处理器,前提是 urlopen 没有返回结果。关于信号模块的更多信息,可以查看这个链接: http://docs.python.org/library/signal.html

撰写回答