File: errorhandling.py

package info (click to toggle)
python-mpd 3.1.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 476 kB
  • sloc: python: 3,148; makefile: 201; sh: 9
file content (138 lines) | stat: -rw-r--r-- 4,074 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#! /usr/bin/env python
#
# Introduction
#
# A python program that continuously polls for song info. Demonstrates how and where to handle errors
# Details
#

from mpd import MPDClient, MPDError, CommandError
import sys


class PollerError(Exception):
    """Fatal error in poller."""


class MPDPoller(object):
    def __init__(self, host="localhost", port="6600", password=None):
        self._host = host
        self._port = port
        self._password = password
        self._client = MPDClient()

    def connect(self):
        try:
            self._client.connect(self._host, self._port)
        # Catch socket errors
        except IOError as err:
            errno, strerror = err
            raise PollerError("Could not connect to '%s': %s" % (self._host, strerror))

        # Catch all other possible errors
        # ConnectionError and ProtocolError are always fatal.  Others may not
        # be, but we don't know how to handle them here, so treat them as if
        # they are instead of ignoring them.
        except MPDError as e:
            raise PollerError("Could not connect to '%s': %s" % (self._host, e))

        if self._password:
            try:
                self._client.password(self._password)

            # Catch errors with the password command (e.g., wrong password)
            except CommandError as e:
                # On CommandErrors we have access to the parsed error response
                # split into errno, offset, command and msg.
                raise PollerError(
                    "Could not connect to '%s': "
                    "password commmand failed: [%d] %s" % (self._host, e.errno, e.msg)
                )

            # Catch all other possible errors
            except (MPDError, IOError) as e:
                raise PollerError(
                    "Could not connect to '%s': "
                    "error with password command: %s" % (self._host, e)
                )

    def disconnect(self):
        # Try to tell MPD we're closing the connection first
        try:
            self._client.close()

        # If that fails, don't worry, just ignore it and disconnect
        except (MPDError, IOError):
            pass

        try:
            self._client.disconnect()

        # Disconnecting failed, so use a new client object instead
        # This should never happen.  If it does, something is seriously broken,
        # and the client object shouldn't be trusted to be re-used.
        except (MPDError, IOError):
            self._client = MPDClient()

    def poll(self):
        try:
            song = self._client.currentsong()

        # Couldn't get the current song, so try reconnecting and retrying
        except (MPDError, IOError):
            # No error handling required here
            # Our disconnect function catches all exceptions, and therefore
            # should never raise any.
            self.disconnect()

            try:
                self.connect()

            # Reconnecting failed
            except PollerError as e:
                raise PollerError("Reconnecting failed: %s" % e)

            try:
                song = self._client.currentsong()

            # Failed again, just give up
            except (MPDError, IOError) as e:
                raise PollerError("Couldn't retrieve current song: %s" % e)

        # Hurray!  We got the current song without any errors!
        print(song)


def main():
    from time import sleep

    poller = MPDPoller()
    poller.connect()

    while True:
        poller.poll()
        sleep(3)


if __name__ == "__main__":
    import sys

    try:
        main()

    # Catch fatal poller errors
    except PollerError as e:
        print("Fatal poller error: %s" % e, file=sys.stderr)
        sys.exit(1)

    # Catch all other non-exit errors
    except Exception as e:
        print("Unexpected exception: %s" % e, file=sys.stderr)
        sys.exit(1)

    # Catch the remaining exit errors
    except Exception:
        sys.exit(0)


# vim: set expandtab shiftwidth=4 softtabstop=4 textwidth=79: