3

我有一个非常基本的代理类(帮助我编写它的朋友坚持认为它是一个装饰器类)用于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] 连接被拒绝

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

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

1 回答 1

3

当没有可用的主机时,你能想出一种优雅的方法来防止程序崩溃吗?

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()
于 2014-08-30T08:18:47.493 回答