xmlrpc library example python xml-rpc

python - library - Establecer el tiempo de espera para xmlrpclib.ServerProxy



xml rpc library python (10)

Estoy usando xmlrpclib.ServerProxy para hacer llamadas RPC a un servidor remoto. Si no hay una conexión de red al servidor, demora los 10 segundos predeterminados para devolver un socket.gaierror a mi programa.

Esto es molesto cuando se hace un desarrollo sin una conexión de red, o si el servidor remoto está inactivo. ¿Hay alguna manera de actualizar el tiempo de espera en mi objeto ServerProxy?

No veo una forma clara de acceder al socket para actualizarlo.


Una solución más directa es en: http://www.devpicayune.com/entry/200609191448

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


Basado en el de antonylesuisse, una versión de trabajo (en python> = 2.6).

# -*- 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)



Aquí hay un código que funciona en Python 2.7 (probablemente para otras versiones 2.x de Python) sin generar AttributeError, la instancia no tiene el atributo ''getresponse'' .

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)


Aquí hay una copia literal de http://code.activestate.com/recipes/473878/

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


Aquí otra solución inteligente y muy pitónica usando Python''s with declaración:

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)

Esta clase se puede usar así:

with MyServerProxy(''http://1.2.3.4'', 20) as proxy: proxy.dummy()


Basado en el de antonylesuisse, pero funciona en Python 2.7.5, resolviendo el problema: la AttributeError: TimeoutHTTP instance has no attribute ''getresponse''

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()


El siguiente ejemplo funciona con Python 2.7.4.

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)


Quería una versión pequeña, limpia, pero también explícita, por lo que basándome en todas las otras respuestas aquí, esto es lo que se me ocurrió:

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)

Al principio, no me di cuenta de que xmlrpclib tiene clases antiguas, por lo que me pareció útil hacer un comentario al respecto, de lo contrario, todo debería ser bastante fácil de explicar.

No veo por qué httplib.HTTP tendría que ser subclasificado también, si alguien puede aclararme sobre esto, por favor hazlo. La solución anterior se prueba y funciona.


limpiar la versión no global.

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()