【问题标题】:How to deal with an unavailable host (ConnectionRefusedError) in a proxy class如何处理代理类中的不可用主机(ConnectionRefusedError)
【发布时间】:2014-10-24 04:08:39
【问题描述】:

我有一个用于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] 连接被拒绝

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

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

【问题讨论】:

    标签: python error-handling proxy mpd


    【解决方案1】:

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

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

    【讨论】:

    • 好答案!事实上,上层对于被拒绝的连接也无能为力。在特定情况下(一个 django 项目),我只想显示一个信息框“MPD 服务器不可用”或类似信息)
    • @speendo Display + log 也许? (见日志模块)
    • @sylvian-leroux 是的。以为我可以直接在 MPDProxy 中以 DRY 方式执行此操作...顺便说一下,我认为 except ConnectionRefusedError:... 应该在 self.connect(self.host, self.port) 之后立即排入,但我不完全确定
    • @speendo 不要太从字面上理解这个例子。它来了就打字。并且没有必要非常集中......如果您发现一个明显的错误,请不要犹豫编辑我的答案。稍后我会审查它。
    猜你喜欢
    • 1970-01-01
    • 2019-06-01
    • 2019-01-18
    • 2012-11-04
    • 1970-01-01
    • 2019-09-17
    • 2020-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多