Тайм-аут для клиентских запросов xmlrpclib
Я использую xmlrpclib Python для отправки запросов в службу xml-rpc.
Есть ли способ установить время ожидания клиента, чтобы мои запросы не зависали вечно, когда сервер недоступен?
Я знаю, что могу глобально установить время ожидания сокета с socket.setdefaulttimeout()
, но это не является предпочтительным.
4 ответа
Чистый подход заключается в определении и использовании пользовательского транспорта, например:! это будет работать только для 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)
Есть пример определения и использования пользовательского транспорта в документах, хотя он использует его для другой цели (доступ через прокси, а не установка тайм-аутов), этот код в основном вдохновлен этим примером.
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
Почему бы и нет:
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.
Альтернативная реализация, которая будет совместима с 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)
Использование супер-метода позволило бы базовой реализации 2.7 поддерживать свою функцию поддержки активности HTTP/1.1, которую он определяет.
Следует отметить, что если вы пытаетесь использовать XML-RPC через соединение / адрес https, замените xmlrpc.SafeTransport
ссылки с xmlrpc.Transport
вместо этого, и, если вы используете реализацию 2.6, используйте httplib.HTTPSConnection
,
Если кто-то пытается сделать это в 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
)