문제

저는 python-mpd2 모듈을 사용하여 GUI 애플리케이션에서 Raspberry Pi의 미디어 플레이어를 제어하고 있습니다.따라서 나는 백그라운드에서 연결 오류 및 시간 초과(문제의 플레이어가 60초 후에 MPD 연결을 끊음)를 적절하게 처리하고 싶습니다.그러나 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은 정말 많습니다.여기에 사용자 정의를 활용하는 자동 마법 솔루션이 있습니다. __getattr__, 래퍼를 반환합니다.

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