Python 设置xmlrpclib.ServerProxy的超时

Python 设置xmlrpclib.ServerProxy的超时,python,xml-rpc,Python,Xml Rpc,我正在使用xmlrpclib.ServerProxy对远程服务器进行RPC调用。如果没有与服务器的网络连接,则默认情况下需要10秒才能将socket.gairror返回到我的程序 当在没有网络连接的情况下进行开发时,或者如果远程服务器关闭,这很烦人。有没有办法更新我的ServerProxy对象上的超时 我找不到一个清晰的方法来访问套接字以更新它。这里是来自 更简单的解决方案是: 清除非全局版本 import xmlrpclib import httplib class TimeoutHTT

我正在使用xmlrpclib.ServerProxy对远程服务器进行RPC调用。如果没有与服务器的网络连接,则默认情况下需要10秒才能将socket.gairror返回到我的程序

当在没有网络连接的情况下进行开发时,或者如果远程服务器关闭,这很烦人。有没有办法更新我的ServerProxy对象上的超时


我找不到一个清晰的方法来访问套接字以更新它。

这里是来自


更简单的解决方案是:


清除非全局版本

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

基于antonylesuisse的版本,一个工作版本(在python上>=2.6)


下面是在Python2.7(可能是其他2.x版本的Python)上运行的代码,该代码不引发AttributeError,实例没有属性“getresponse”


这里是另一个使用Python的
with
语句的智能且非常pythonic解决方案:

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)
此类的使用方式如下:

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

以下示例适用于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)

基于antonylesuisse的一个,但适用于Python 2.7.5,解决了以下问题:
AttributeError:TimeoutHTTP实例没有属性“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()

我想要一个小的,干净的,但也是明确的版本,所以根据这里的所有其他答案,我得出以下结论:

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)
起初我没有意识到
xmlrpclib
有旧式的类,所以我发现对它进行注释很有用,否则一切都应该是不言自明的


我不明白为什么
httplib.HTTP
也必须被子类化,如果有人能告诉我这一点,请这样做。上面的解决方案已经尝试过并且有效。

套接字如何应用于xmlrpclib?我们从来没有在x上设置套接字。@ashchristopher:我没有测试过这段代码,但看起来setdefaulttimeout是一个全局默认值。因此,如果xmlrpclib没有设置任何特定的超时值,它可能会使用全局默认值。@MiniQuark:正确,它是全局默认值(无),这意味着新套接字对象没有超时。setdefaulttimeout函数的优点是它适用于HTTPS/SSL套接字,其他发布的示例仅适用于HTTP。@Jeff Bauer:使用HTTP的社区wiki示例也可以通过将HTTPSConnection、HTTPS和SafeTransport子类化来完成。这应该是同样的工作方式。绝对是我的代码的赢家。我添加了2行,完成了,而其他人建议添加3个类。TL;顺便说一句,DR对我很有效,Debian上的Python2.5。顺便说一句,您在导入中有一个伪“.”字符,“导入套接字”未使用。在Python 2.7上不适用于我。当我进行RPC调用时,我得到错误
AttributeError:TimeoutHTTP实例没有属性“getresponse”
get AttributeError:module“http.client”在迁移到python3时没有属性“HTTPClient”。它看起来像是不完整的代码段。
with MyServerProxy('http://1.2.3.4', 20) as proxy:
    proxy.dummy()
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)
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()
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)