虽然
socket.setsocketimeout将为新套接字设置默认超时,但是如果您不直接使用套接字,则可以轻松覆盖该设置。特别是,如果库
socket.setblocking在其套接字上调用,它将重置超时。
urllib2.open有一个超时参数,但是,中没有超时
urllib2.Request。在使用时
mechanize,应参考其文档:
从Python
2.6开始,urllib2在内部对Request对象使用.timeout属性。但是,urllib2.Request没有超时构造函数参数,而urllib2.urlopen()会忽略此参数。mechanize.Request具有超时构造函数参数,该参数用于设置相同名称的属性,mechanize.urlopen()不会忽略超时属性。
来源: http :
//wwwsearch.sourceforge.net/mechanize/documentation.html
- -编辑 - -
如果
socket.setsockettimeout超时
mechanize值或传递超时值的值较小但不适用于较高的值,则问题的根源可能会完全不同。一件事是您的库可能会打开多个连接(这里记为@CédricJulien),因此超时适用于socket.open的每次尝试,如果第一次失败就不会停止–可能需要
timeout* num_of_conn几秒钟的时间。另一件事是
socket.recv:如果连接确实很慢并且您不够幸运,则整个请求可能会占用
timeout *incoming_bytes每个
socket.recv我们可以得到一个字节的字节,并且每个这样的调用都可能占用
timeout秒。由于您不太可能遭受这种黑暗的场景(每个超时秒一个字节?您必须是一个非常粗鲁的男孩)的痛苦,因此很可能需要花很长时间才能获得非常慢的连接和很高的超时。
您唯一的解决方案是对整个请求强制超时,但是这里与套接字无关。如果您使用的是Unix,则可以对
ALARM信号使用简单的解决方案。您将信号设置为以
timeout秒为单位发出信号,您的请求将被终止(不要忘记捕获它)。您可能希望使用
with语句使其整洁易用,例如:
import signal, timedef request(arg): """Your http request""" time.sleep(2) return argclass Timeout(): """Timeout class using ALARM signal""" class Timeout(Exception): pass def __init__(self, sec): self.sec = sec def __enter__(self): signal.signal(signal.SIGALRM, self.raise_timeout) signal.alarm(self.sec) def __exit__(self, *args): signal.alarm(0) # disable alarm def raise_timeout(self, *args): raise Timeout.Timeout()# Run block of pre with timeoutstry: with Timeout(3): print request("Request 1") with Timeout(1): print request("Request 2")except Timeout.Timeout: print "Timeout"# Prints "Request 1" and "Timeout"如果要比这更具便携性,则必须使用一些较大的枪,例如
multiprocessing,这样您将生成一个流程来调用您的请求,并在过期时终止该请求。由于这是一个单独的过程,因此您必须使用某种方法将结果传输回您的应用程序
multiprocessing.Pipe。示例如下:
from multiprocessing import Process, Pipeimport timedef request(sleep, result): """Your http request example""" time.sleep(sleep) return resultclass TimeoutWrapper(): """Timeout wrapper using separate process""" def __init__(self, func, timeout): self.func = func self.timeout = timeout def __call__(self, *args, **kargs): """Run func with timeout""" def pmain(pipe, func, args, kargs): """Function to be called in separate process""" result = func(*args, **kargs) # call func with passed arguments pipe.send(result) # send result to pipe parent_pipe, child_pipe = Pipe() # Pipe for retrieving result of func p = Process(target=pmain, args=(child_pipe, self.func, args, kargs)) p.start() p.join(self.timeout) # wait for prcoess to end if p.is_alive(): p.terminate() # Timeout, kill return None # or raise exception if None is acceptable result else: return parent_pipe.recv() # OK, get resultprint TimeoutWrapper(request, 3)(1, "OK") # prints OKprint TimeoutWrapper(request, 1)(2, "Timeout") # prints None
如果要强制在固定秒数后终止请求,您实际上没有太多选择。
socket.timeout将为单个套接字操作(连接/接收/发送)提供超时,但是如果有多个套接字,则执行时间会很长。



