如何处理代理类中的不可用主机(ConnectionRefusedError)

时间:2014-08-30 07:54:31

标签: python error-handling proxy mpd

python-mpd2我有一个非常基本的代理类(一位帮我编码的朋友坚持认为它是一个装饰类)。

该课程看起来像这样

import mpd

class MPDProxy:
    def __init__(self, host="localhost", port=6600, timeout=10):
        self.client = mpd.MPDClient()
        self.host = host
        self.port = port

        self.client.timeout = timeout
        self.connect(host, port)

    def __getattr__(self, name):
        return self._call_with_reconnect(getattr(self.client, name))

    def connect(self, host, port):
        self.client.connect(host, port)

    def _call_with_reconnect(self, func):
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except mpd.ConnectionError:
                self.connect(self.host, self.port)
                return func(*args, **kwargs)
        return wrapper

mpd_proxy = MPDProxy()

到目前为止,只要有可用于连接的mpd主机,这种方法效果很好。如果没有mpd服务器,我会得到

  

ConnectionRefusedError:[Errno 111]拒绝连接

我正在寻找处理此异常的好模式

  • 当没有主机可用时,您能想到一种优雅的方法来防止程序崩溃吗?
  • 无论何时调用代理,我都应该在代理内部或外部捕获异常吗?
  • 字符串“Host not available”(或类似)作为返回值是个好主意,还是可以更好地通知调用代理的方法/函数?

1 个答案:

答案 0 :(得分:2)

  

如果没有可用的主机,您能想到一种优雅的方法来阻止程序崩溃吗?

try ... except;)


  

每当代理被调用时,我应该在代理内部还是外部捕获异常?

你应该问自己的问题是"谁能*处理这个例外?"


显然,代理人可以选择任何合理的东西来修复" ConnectionRefusedError。所以它必须在上层处理。


  

字符串"主机不可用" (或类似的)作为返回值是一个好主意,还是可以更好地通知调用代理的方法/函数?

糟糕的主意。通知"上层的正常方式"发生异常比raise例外。或者让一个引发的异常传播起来。


具体地:

class MPDProxy:
    def _call_with_reconnect(self, func):
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except mpd.ConnectionError:
                self.connect(self.host, self.port)
                # ^^^^^^ This lime might raise `ConnectionRefusedError`
                # as there is no `except` block around, this exception
                # is automatically propagated     

                return func(*args, **kwargs)
        return wrapper

try:
    mpd_proxy = MPDProxy()
    r = mdp_proxy._call_with_reconnect(whatever)
except ConnectionRefusedError:
    do_somesible_sensible()