2010-03-11 147 views
4

我正在使用Python的xmlrpclib向xml-rpc服务发出请求。xmlrpclib客户端请求超时

有没有办法设置客户端超时,所以当服务器不可用时,我的请求不会永远挂起?

我知道我可以通过socket.setdefaulttimeout()在全局范围内设置套接字超时,但这并不可取。

回答

12

干净的方法是定义和使用自定义运输,例如: !这将只适用于python2.7!

import xmlrpclib, httplib 

class TimeoutTransport(xmlrpclib.Transport): 
    timeout = 10.0 
    def set_timeout(self, timeout): 
     self.timeout = timeout 
    def make_connection(self, host): 
     h = httplib.HTTPConnection(host, timeout=self.timeout) 
     return h 

t = TimeoutTransport() 
t.set_timeout(20.0) 
server = xmlrpclib.Server('http://time.xmlrpc.com/RPC2', transport=t) 

虽然它(通过代理访问,而不是设置超时)将其用于不同的目的有定义和在the docs使用自定义传输的一个例子,此代码基本上是由该实施例的启发。

+0

这个例子不适用于python 2.5,2.6(TimeoutTransport实例没有属性'proxy'),httplib.HTTP也没有超时值。 – Ib33X 2010-11-10 14:41:35

+1

我注意到Python 2.7中最初的'Transport.make_connection'方法有更多的逻辑来处理keep-alive,额外的头文件等,它也使用'httplib.HTTPConnection'而不是'httplib.HTTP'。我不知道在典型用例中这一点很重要,但我决定复制原始代码并将其更改为使用超时,如上面的答案中所示。 – 2014-09-23 20:45:26

8

DOH,使这项工作在python2.6的+做到这一点:

class HTTP_with_timeout(httplib.HTTP): 
    def __init__(self, host='', port=None, strict=None, timeout=5.0): 
     if port == 0: port = None 
     self._setup(self._connection_class(host, port, strict, timeout=timeout)) 

    def getresponse(self, *args, **kw): 
     return self._conn.getresponse(*args, **kw) 

class TimeoutTransport(xmlrpclib.Transport): 
    timeout = 10.0 
    def set_timeout(self, timeout): 
     self.timeout = timeout 
    def make_connection(self, host): 
     h = HTTP_with_timeout(host, timeout=self.timeout) 
     return h 
+0

适用于2.6和2.7,谢谢! – 2012-07-20 14:22:06

5

为什么不:

class TimeoutTransport(xmlrpclib.Transport): 

def setTimeout(self, timeout): 
    self._timeout = timeout 

def make_connection(self, host): 
    return httplib.HTTPConnection(host, timeout=self._timeout) 

毕竟,HTTPHTTPS似乎不过是旧版Python版本的兼容性类。

3

的替代实现,这将是兼容的Python 2.7将如下所示(带有注释包含,如果你使用Python 2.6,你会想什么):

import socket 
import xmlrpclib 

class TimeoutTransport (xmlrpclib.Transport): 
    """ 
    Custom XML-RPC transport class for HTTP connections, allowing a timeout in 
    the base connection. 
    """ 

    def __init__(self, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, use_datetime=0): 
     xmlrpclib.Transport.__init__(self, use_datetime) 
     self._timeout = timeout 

    def make_connection(self, host): 
     # If using python 2.6, since that implementation normally returns the 
     # HTTP compatibility class, which doesn't have a timeout feature. 
     #import httplib 
     #host, extra_headers, x509 = self.get_host_info(host) 
     #return httplib.HTTPConnection(host, timeout=self._timeout) 

     conn = xmlrpclib.Transport.make_connection(self, host) 
     conn.timeout = self._timeout 
     return conn 

# Example use 
t = TimeoutTransport(timeout=10) 
server = xmlrpclib.ServerProxy('http://time.xmlrpc.com/RPC2', transport=t) 

采用了超方法将允许底层的2.7实现来维护其定义的HTTP/1.1保持活动功能。

在这里要注意的是,如果你想使用XML-RPC通过HTTPS连接/地址,与xmlrpc.Transport取代xmlrpc.SafeTransport引用代替,而且,如果您使用的是2.6的实现,使用httplib.HTTPSConnection