3

I have a very basic proxy class (a friend who helped me coding it insists it's a decorator class instead) for python-mpd2.

The class looks like this

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

This works well so far, as long as there is an mpd host available to connect to. If there is no mpd server, I get

ConnectionRefusedError: [Errno 111] Connection refused

I'm looking for good patterns to deal with this Exception

  • Can you think of an elegant way to prevent the program to crash, when there is no host available?
  • Should I catch the exception within the proxy or outside, whenever the proxy is called?
  • Is a string "Host not available" (or similar) as a return value a good idea or can a method/function calling the proxy be informed in a better way?
speendo
  • 13,045
  • 22
  • 71
  • 107

1 Answers1

3

Can you think of an elegant way to prevent the program to crash, when there is no host available?

try ... except ;)


Should I catch the exception within the proxy or outside, whenever the proxy is called?

The question you should ask yourself is "who is *able* to deal with that exception?"


Obviously, the proxy can't to anything sensible to "fix" ConnectionRefusedError. So it has to be handled at upper levels.


Is a string "Host not available" (or similar) as a return value a good idea or can a method/function calling the proxy be informed in a better way?

Bad idea. The normal way of informing "upper levels" than an exception has occurred is to raise an exception. Or to let a raised exception propagate up.


Concretely:

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()
Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
  • good answer! In fact also the upper level cannot do much about the refused connection. In the specific case (a django project) I would just want an infobox "MPD server not available" or similar to be displayed) – speendo Aug 30 '14 at 08:31
  • 1
    @speendo Display + log maybe ? (see the logging module) – Sylvain Leroux Aug 30 '14 at 08:36
  • @sylvian-leroux yes. Thought I could maybe do this in a DRY way directly in the MPDProxy... by the way, I think the `except ConnectionRefusedError:...` should go in the line right after `self.connect(self.host, self.port)` but I'm not entirely sure – speendo Aug 30 '14 at 08:40
  • @speendo Don't take that example too literally. It typed as it came. And wasn't necessary very concentrated... If you spot an obvious mistake don't hesitate to edit my answer. I'll review it later. – Sylvain Leroux Aug 30 '14 at 08:42