Вопрос

Я использую модуль Python-MPD2 для управления медиаплеером на Raspberry Pi в приложении GUI. Таким образом, я хотел бы изящно обрабатывать ошибки подключения и тайм-аута (игрок в вопросе падает MPD соединения через 60 секунд) на заднем плане. Тем не менее, модуль MPD не имеет единой точки записи, через который все команды отправляются или информация извлекается, что я могу исправить.

Я хотел бы, чтобы класс, который позволяет доступу ко всем то же методам, что и MPD.MPDClient, но давайте добавим мою собственную обработку ошибок. Другими словами, если я сделаю:

client.play()
.

И ошибка подключения брошена, я бы хотел поймать его и повторю ту же команду. Кроме небольшой задержки, вызванной необходимостью повторного подключения к серверу, пользователь не должен заметить, что что-то невели.

До сих пор, вот решение, с которым я придумал. Он работает в моем приложении, но на самом деле не соответствует моим целям.

from functools import partial
from mpd import MPDClient, ConnectionError

class PersistentMPDClient(object):
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.client = MPDClient()
        self.client.connect(self.host, self.port)

    def command(self, cmd, *args, **kwargs):
        command_callable = partial(self.client.__getattribute__(cmd), *args, **kwargs)
        try:
            return command_callable()
        except ConnectionError:
            # Mopidy drops our connection after a while, so reconnect to send the command
            self.client._soc = None
            self.client.connect(self.host, self.port)
            return command_callable()
.

Я мог бы добавить метод в этот класс для каждой команды MPD, например.:

def play(self):
    return self.command("play")
.

Но это кажется далеко от лучшего способа достичь его.

Это было полезно?

Решение

Если вы не возражаете против создания списка всех 91 строк, формирующихся Имена команд , вы можете сделать что-то вдоль линий Этот ответ .Я считаю, что этот подход имеет много преимуществ, потому что это связано с меньшей волшебной.

OTOH, 91 действительно много.Итак, вот автоматическое решение, использующее пользовательский генеракодицетагкод, который возвращает обертку:

from functools import partial
import types

class DummyClient(object):
    def connect(self, *a, **kw): print 'connecting %r %r' % (a, kw)
    def play(self): print 'playing'
    def stop(self): print 'stopping'

class PersistentMPDClient(object):
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.client = DummyClient()
        self.client.connect(self.host, self.port)

    def __getattr__(self, attr, *args):
        cmd = getattr(self.client, attr, *args)
        if isinstance(cmd, types.MethodType):
            # a method -- wrap
            return lambda *a, **kw: self.command(attr, *a, **kw)
        else:
            # anything else -- return unchanged
            return cmd

    def command(self, cmd, *args, **kwargs):
        command_callable = partial(self.client.__getattribute__(cmd), *args, **kwargs)
        try:
            return command_callable()
        except ConnectionError:
            # Mopidy drops our connection after a while, so reconnect to send the command
            self.client._soc = None
            self.client.connect(self.host, self.port)
            return command_callable()

c = PersistentMPDClient(hostname, port)
c.play()
c.stop()
.

Как я писал это, я заметил @mattoufoutu разместил подобное решение (хотя есть некоторые различия).Я не знаю, почему он / он удалил его ... Если этот ответ становится восстановленным, я бы с удовольствием дал ему кредит, это заслуживает.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top