2010-03-11 4 views
4

J'utilise xmlrpclib de Python pour effectuer des requêtes sur un service xml-rpc.Délai d'attente pour les requêtes client xmlrpclib

Existe-t-il un moyen de définir un délai d'attente pour le client, afin que mes demandes ne soient pas bloquées indéfiniment lorsque le serveur n'est pas disponible?

Je sais que je peux globalement définir un délai de socket avec socket.setdefaulttimeout(), mais ce n'est pas préférable.

Répondre

12

L'approche propre consiste à définir et utiliser un transport personnalisé, par exemple: ! cela ne fonctionnera que pour 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) 

Il y a un exemple de définir et d'utiliser un transport personnalisé dans the docs, bien qu'il utilise dans un but différent (accès via un proxy, plutôt que de définir les délais d'attente), ce code est essentiellement inspiré par cet exemple.

+0

cet exemple ne fonctionne pas sur python 2.5, 2.6 (l'instance de TimeoutTransport n'a pas d'attribut 'proxy') aussi httplib.HTTP n'a pas de valeur de timeout. – Ib33X

+1

J'ai remarqué que la méthode 'Transport.make_connection' d'origine dans Python 2.7 a plus de logique pour gérer keep-alive, en-têtes supplémentaires, etc., et qu'elle utilise aussi' httplib.HTTPConnection' et non 'httplib.HTTP'. Je ne sais pas est-ce important dans les cas d'utilisation typiques, mais j'ai décidé de copier le code original et de le changer pour utiliser les délais d'expiration comme indiqué dans la réponse ci-dessus. –

8

doh, pour faire ce travail en python2.6 + faire ceci:

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

Fonctionne à la fois sur 2.6 et 2.7, merci! –

5

Pourquoi ne pas:

class TimeoutTransport(xmlrpclib.Transport): 

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

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

?

Après tout, HTTP et HTTPS semblent ne pas être plus que des classes de compatibilité pour les anciennes versions de Python.

3

Une implémentation alternative qui serait compatible avec Python 2.7 serait le suivant (avec un commentaire contenant ce que vous voulez si vous utilisez 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) 

Utilisation du super-méthode permettrait l'implémentation sous-jacente 2.7 pour maintenir sa fonctionnalité HTTP/1.1 keep-alive qu'elle définit.

Une chose à noter est que si vous essayez d'utiliser XML-RPC via une connexion https/adresse, remplacer xmlrpc.SafeTransport références avec xmlrpc.Transport à la place, et, si vous utilisez la mise en œuvre 2.6, utilisez httplib.HTTPSConnection.

Questions connexes