Set timeout for xmlrpclib.ServerProxy
我正在使用xmlrpclib.serverproxy对远程服务器进行RPC调用。如果没有到服务器的网络连接,默认情况下需要10秒钟才能将socket.gaiError返回到我的程序。
如果在没有网络连接的情况下进行开发,或者如果远程服务器已关闭,这会很烦人。有没有方法更新我的serverproxy对象上的超时?
我看不到一个明确的方法来访问套接字来更新它。
更直接的解决方案是:http://www.devpicayune.com/entry/2006091448
1 2 3 4 5 6 7 | import xmlrpclib import socket x = xmlrpclib.ServerProxy('http:1.2.3.4') socket.setdefaulttimeout(10) #set the timeout to 10 seconds x.func_name(args) #times out after 10 seconds socket.setdefaulttimeout(None) #sets the default back |
清除非全局版本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import xmlrpclib import httplib class TimeoutHTTPConnection(httplib.HTTPConnection): def connect(self): httplib.HTTPConnection.connect(self) self.sock.settimeout(self.timeout) class TimeoutHTTP(httplib.HTTP): _connection_class = TimeoutHTTPConnection def set_timeout(self, timeout): self._conn.timeout = timeout class TimeoutTransport(xmlrpclib.Transport): def __init__(self, timeout=10, *l, **kw): xmlrpclib.Transport.__init__(self, *l, **kw) self.timeout = timeout def make_connection(self, host): conn = TimeoutHTTP(host) conn.set_timeout(self.timeout) return conn class TimeoutServerProxy(xmlrpclib.ServerProxy): def __init__(self, uri, timeout=10, *l, **kw): kw['transport'] = TimeoutTransport( timeout=timeout, use_datetime=kw.get('use_datetime', 0)) xmlrpclib.ServerProxy.__init__(self, uri, *l, **kw) if __name__ =="__main__": s = TimeoutServerProxy('http://127.0.0.1:9090', timeout=2) s.dummy() |
我已经研究了几种解决这个问题的方法,到目前为止,最优雅的描述如下:https://seattle.cs.washington.edu/browser/seattle/trunk/demokit/timeout_xmlrpclib.py?转速=692
这项技术最初是在这里介绍的,但是这个链接是死的:http://blog.bjola.ca/2007/08/using-timeout-with-xmlrpclib.html
这适用于python 2.5和2.6。新的链接声称也可以与Python3.0一起使用。
我想要一个小的,干净的,但也明确的版本,所以基于这里的所有其他答案,这是我想到的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import xmlrpclib class TimeoutTransport(xmlrpclib.Transport): def __init__(self, timeout, use_datetime=0): self.timeout = timeout # xmlrpclib uses old-style classes so we cannot use super() xmlrpclib.Transport.__init__(self, use_datetime) def make_connection(self, host): connection = xmlrpclib.Transport.make_connection(self, host) connection.timeout = self.timeout return connection class TimeoutServerProxy(xmlrpclib.ServerProxy): def __init__(self, uri, timeout=10, transport=None, encoding=None, verbose=0, allow_none=0, use_datetime=0): t = TimeoutTransport(timeout) xmlrpclib.ServerProxy.__init__(self, uri, t, encoding, verbose, allow_none, use_datetime) proxy = TimeoutServerProxy(some_url) |
我一开始没有意识到
我不明白为什么
下面是在python 2.7上工作的代码(可能适用于其他2.x版本的python),而不引发attributeError,实例没有属性"getResponse"。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | class TimeoutHTTPConnection(httplib.HTTPConnection): def connect(self): httplib.HTTPConnection.connect(self) self.sock.settimeout(self.timeout) class TimeoutHTTP(httplib.HTTP): _connection_class = TimeoutHTTPConnection def set_timeout(self, timeout): self._conn.timeout = timeout class TimeoutTransport(xmlrpclib.Transport): def __init__(self, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, *args, **kwargs): xmlrpclib.Transport.__init__(self, *args, **kwargs) self.timeout = timeout def make_connection(self, host): if self._connection and host == self._connection[0]: return self._connection[1] chost, self._extra_headers, x509 = self.get_host_info(host) self._connection = host, httplib.HTTPConnection(chost) return self._connection[1] transport = TimeoutTransport(timeout=timeout) xmlrpclib.ServerProxy.__init__(self, uri, transport=transport, allow_none=True) |
基于Antonylesuisse,一个工作版本(在python上>=2.6)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # -*- coding: utf8 -*- import xmlrpclib import httplib import socket class TimeoutHTTP(httplib.HTTP): def __init__(self, host='', port=None, strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): if port == 0: port = None self._setup(self._connection_class(host, port, strict, timeout)) class TimeoutTransport(xmlrpclib.Transport): def __init__(self, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, *args, **kwargs): xmlrpclib.Transport.__init__(self, *args, **kwargs) self.timeout = timeout def make_connection(self, host): host, extra_headers, x509 = self.get_host_info(host) conn = TimeoutHTTP(host, timeout=self.timeout) return conn class TimeoutServerProxy(xmlrpclib.ServerProxy): def __init__(self, uri, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, *args, **kwargs): kwargs['transport'] = TimeoutTransport(timeout=timeout, use_datetime=kwargs.get('use_datetime', 0)) xmlrpclib.ServerProxy.__init__(self, uri, *args, **kwargs) |
以下是http://code.activestate.com/recipes/473878的逐字副本/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None): import threading class InterruptableThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.result = None def run(self): try: self.result = func(*args, **kwargs) except: self.result = default it = InterruptableThread() it.start() it.join(timeout_duration) if it.isAlive(): return default else: return it.result |
基于Antonylesuisse的,但是在python 2.7.5上工作,解决了这个问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | class TimeoutHTTP(httplib.HTTP): def __init__(self, host='', port=None, strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): if port == 0: port = None self._setup(self._connection_class(host, port, strict, timeout)) def getresponse(self, *args, **kw): return self._conn.getresponse(*args, **kw) class TimeoutTransport(xmlrpclib.Transport): def __init__(self, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, *l, **kw): xmlrpclib.Transport.__init__(self, *l, **kw) self.timeout=timeout def make_connection(self, host): host, extra_headers, x509 = self.get_host_info(host) conn = TimeoutHTTP(host, timeout=self.timeout) return conn class TimeoutServerProxy(xmlrpclib.ServerProxy): def __init__(self, uri, timeout= socket._GLOBAL_DEFAULT_TIMEOUT, *l, **kw): kw['transport']=TimeoutTransport(timeout=timeout, use_datetime=kw.get('use_datetime',0)) xmlrpclib.ServerProxy.__init__(self, uri, *l, **kw) proxy = TimeoutServerProxy('http://127.0.0.1:1989', timeout=30) print proxy.test_connection() |
下面的示例适用于python 2.7.4。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import xmlrpclib from xmlrpclib import * import httplib def Server(url, *args, **kwargs): t = TimeoutTransport(kwargs.get('timeout', 20)) if 'timeout' in kwargs: del kwargs['timeout'] kwargs['transport'] = t server = xmlrpclib.Server(url, *args, **kwargs) return server TimeoutServerProxy = Server class TimeoutTransport(xmlrpclib.Transport): def __init__(self, timeout, use_datetime=0): self.timeout = timeout return xmlrpclib.Transport.__init__(self, use_datetime) def make_connection(self, host): conn = xmlrpclib.Transport.make_connection(self, host) conn.timeout = self.timeout return connrpclib.Server(url, *args, **kwargs) |
下面是另一个使用python的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import socket import xmlrpc.client class MyServerProxy: def __init__(self, url, timeout=None): self.__url = url self.__timeout = timeout self.__prevDefaultTimeout = None def __enter__(self): try: if self.__timeout: self.__prevDefaultTimeout = socket.getdefaulttimeout() socket.setdefaulttimeout(self.__timeout) proxy = xmlrpc.client.ServerProxy(self.__url, allow_none=True) except Exception as ex: raise Exception("Unable create XMLRPC-proxy for url '%s': %s" % (self.__url, ex)) return proxy def __exit__(self, type, value, traceback): if self.__prevDefaultTimeout is None: socket.setdefaulttimeout(self.__prevDefaultTimeout) |
此类的使用方式如下:
1 2 | with MyServerProxy('http://1.2.3.4', 20) as proxy: proxy.dummy() |