4

我正在使用 Python 的 xmlrpclib 向 xml-rpc 服务发出请求。

有没有办法设置客户端超时,所以当服务器不可用时我的请求不会永远挂起?

我知道我可以使用 全局设置套接字超时socket.setdefaulttimeout(),但这并不可取。

4

5 回答 5

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)

在docs中有一个定义和使用自定义传输的示例,尽管它用于不同的目的(通过代理访问,而不是设置超时),此代码基本上是受该示例的启发。

于 2010-03-11T15:37:48.640 回答
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
于 2011-05-16T08:42:05.427 回答
5

为什么不:

class TimeoutTransport(xmlrpclib.Transport):

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

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

?

毕竟,HTTP似乎HTTPS只是旧 Python 版本的兼容性类。

于 2011-06-28T16:40:19.180 回答
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)

使用 super-method 将允许底层 2.7 实现维护其定义的 HTTP/1.1 保持活动功能。

需要注意的是,如果您尝试通过 https 连接/地址使用 XML-RPC,请将xmlrpc.SafeTransport引用替换为xmlrpc.Transport,如果您使用的是 2.6 实现,请使用httplib.HTTPSConnection.

于 2013-06-06T20:19:49.177 回答
0

如果有人试图在 Python 3+ 中执行此操作并使用上下文 kwarg(在我的情况下允许连接到自签名 SSL 证书),则以下代码适用于我

class TimeoutTransport (xmlrpc.client.SafeTransport):
    def __init__(self, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, context=None, use_datetime=0):
        xmlrpc.client.Transport.__init__(self, use_datetime)
        self._timeout = timeout
        self.context = context

    def make_connection(self, host):
        conn = xmlrpc.client.SafeTransport.make_connection(self, host)
        conn.timeout = self._timeout
        return conn

然后调用:

 url = "https://localhost:8080/RPC2"
 t = TimeoutTransport(timeout=2, context=ssl._create_unverified_context())
 xml_conn = xmlrpc.client.ServerProxy(
        url,
        transport=t
    )
于 2020-05-26T13:31:40.183 回答