python 为 xmlrpclib.ServerProxy 设置超时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/372365/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 19:58:32  来源:igfitidea点击:

Set timeout for xmlrpclib.ServerProxy

pythonxml-rpc

提问by ashchristopher

I am using xmlrpclib.ServerProxy to make RPC calls to a remote server. If there is not a network connection to the server it takes the default 10 seconds to return a socket.gaierror to my program.

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

This is annoying when doing development without a network connection, or if the remote server is down. Is there a way to update the timeout on my ServerProxy object?

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

I can't see a clear way to get access to the socket to update it.

我看不到访问套接字以更新它的明确方法。

回答by azarias

An more straightforward solution is at: http://www.devpicayune.com/entry/200609191448

更直接的解决方案是:http: //www.devpicayune.com/entry/200609191448

import xmlrpclib 
import socket

x = xmlrpclib.ServerProxy('http:1.2.3.4')  
socket.setdefaulttimeout(10)        #set the timeout to 10 seconds 
x.func_name(args)                   #times out after 10 seconds
socket.setdefaulttimeout(None)      #sets the default back

回答by antonylesuisse

clean non global version.

干净的非全球版本。

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

回答by Markus Amalthea Magnuson

I wanted a small, clean, but also explicit version, so based on all other answers here, this is what I came up with:

我想要一个小而干净但也明确的版本,所以基于这里的所有其他答案,这就是我想出的:

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)

I didn't realize at first xmlrpclibhas old-style classes so I found it useful with a comment on that, otherwise everything should be pretty self-explanatory.

起初我没有意识到xmlrpclib有旧式的类,所以我发现它很有用,对此发表评论,否则一切都应该是不言自明的。

I don't see why httplib.HTTPwould have to be subclassed as well, if someone can enlighten me on this, please do. The above solution is tried and works.

我不明白为什么httplib.HTTP还必须被子类化,如果有人可以启发我,请这样做。上述解决方案已尝试并有效。

回答by mtasic85

Here is code that works on Python 2.7 (probably for other 2.x versions of Python) without raising AttributeError, instance has no attribute 'getresponse'.

这是适用于 Python 2.7(可能适用于其他 2.x 版本的 Python)的代码,不会引发AttributeError,实例没有属性 'getresponse'


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=socket._GLOBAL_DEFAULT_TIMEOUT, *args, **kwargs):
        xmlrpclib.Transport.__init__(self, *args, **kwargs)
        self.timeout = timeout

    def make_connection(self, host):
        if self._connection and host == self._connection[0]:
            return self._connection[1]

        chost, self._extra_headers, x509 = self.get_host_info(host)
        self._connection = host, httplib.HTTPConnection(chost)
        return self._connection[1]


transport = TimeoutTransport(timeout=timeout)
xmlrpclib.ServerProxy.__init__(self, uri, transport=transport, allow_none=True)

回答by KangOl

Based on the one from antonylesuisse, a working version (on python >= 2.6).

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

# -*- coding: utf8 -*-
import xmlrpclib
import httplib
import socket

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

class TimeoutTransport(xmlrpclib.Transport):
    def __init__(self, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, *args, **kwargs):
        xmlrpclib.Transport.__init__(self, *args, **kwargs)
        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,
                 *args, **kwargs):
        kwargs['transport'] = TimeoutTransport(timeout=timeout,
                                    use_datetime=kwargs.get('use_datetime', 0))
        xmlrpclib.ServerProxy.__init__(self, uri, *args, **kwargs)

回答by monkut

Here is a verbatim copy from http://code.activestate.com/recipes/473878/

这是来自http://code.activestate.com/recipes/473878/的逐字副本

def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
    import threading
    class InterruptableThread(threading.Thread):
        def __init__(self):
        threading.Thread.__init__(self)
        self.result = None

        def run(self):
            try:
                self.result = func(*args, **kwargs)
            except:
                self.result = default

    it = InterruptableThread()
    it.start()
    it.join(timeout_duration)
    if it.isAlive():
        return default
    else:
        return it.result

回答by gecco

Here another smart and very pythonicsolution using Python's withstatement:

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

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)

This class can be used like this:

这个类可以这样使用:

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

回答by Slava

The following example works with Python 2.7.4.

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

回答by lengxuehx

Based on the one from antonylesuisse, but works on Python 2.7.5, resolving the problem:AttributeError: TimeoutHTTP instance has no attribute 'getresponse'

基于 antonylesuisse 的,但适用于 Python 2.7.5,解决了问题:AttributeError: TimeoutHTTP instance has no attribute '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()