2011-04-06 99 views
12

我使用Python's urllib2发送一个HTTP POST:与Python检测挂起urllib2.urlopen

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永远不会返回的实例。

我知道它永远不会返回,因为我们的实际代码中有一些日志行会在前后调用,并且发生此问题时只会调用之前的调用并且脚本永远挂起。

检测/处理此问题的最佳方法是什么?

+0

正在修改默认的套接字超时不适合你吗? – jathanism 2011-04-06 13:54:39

+0

我遇到了同样的问题,你解决了吗? – ajaxhe 2016-11-15 07:15:50

回答

9

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

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

+1

...然后在处理程序中,我可以抛出异常,这将被外部try/except块捕获。 – DavidM 2011-04-07 21:51:46

+2

这不适用于Windows('signal.alarm()'不支持) – 2011-10-02 12:38:36

+1

@Sebastien,[here](http://stackoverflow.com/questions/644073/signal-alarm-replacement-in-windows-python )你可以在Windows系统中找到关于signal.alarm()的讨论 – Manuel 2011-10-05 08:26:12