2010-03-11 117 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