我正在使用Python的xmlrpclib向xml-rpc服务发出请求。
有没有办法设置客户端超时,所以当服务器不可用时,我的请求不会永远挂起?
我知道我可以使用socket.setdefaulttimeout()
全局设置套接字超时,但这不是首选。
答案 0 :(得分: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)
有一个在the docs中定义和使用自定义传输的示例,虽然它将其用于不同目的(通过代理访问,而不是设置超时),但此代码基本上受到该示例的启发。 / p>
答案 1 :(得分: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
答案 2 :(得分: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的兼容性类。
答案 3 :(得分: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方法将允许底层的2.7实现维护它定义的HTTP / 1.1保持活动功能。
需要注意的是,如果您尝试在https连接/地址上使用XML-RPC,请将xmlrpc.SafeTransport
引用替换为xmlrpc.Transport
,并且,如果您使用的是2.6实施,使用httplib.HTTPSConnection
。
答案 4 :(得分: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
)