forked from Mic92/python-mpd2
-
Notifications
You must be signed in to change notification settings - Fork 1
/
errorhandling.py
138 lines (105 loc) · 4.04 KB
/
errorhandling.py
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:
sys.exit(0)
# vim: set expandtab shiftwidth=4 softtabstop=4 textwidth=79: