Kleines Programm für Openbox\MPD

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Tayce
User
Beiträge: 56
Registriert: Sonntag 22. April 2007, 18:26
Wohnort: München
Kontaktdaten:

Ich hab mir mal ein kleines Script geschrieben dass ich vom Openbox-Menü aus starten kann um MPD zu stoppen, das nächste Lied zu spielen usw...
Genutzt wird python-mpd.
Hier mal der Code:

Code: Alles auswählen

#!/usr/bin/env python
import sys
import mpd
class Player(object):
    def __init__(self):
        self.client=mpd.MPDClient()
        self.client.connect("localhost", 6600)
    def next(self):
        self.client.next()
    def previous(self):
        self.client.previous()
    def play(self):
        self.client.play()
    def pause(self):
        self.client.pause()
    def stop(self):
        self.client.stop()
    def close(self):
        self.client.close()
    def getcommand(self):
        try:
            self.command = sys.argv[1]
        except:
            print "Error"
    def doit(self):
        if self.command == "-next":
            self.next()
        if self.command == "-previous":
            self.previous()
        if self.command == "-play":
            self.play()
        if self.command == "-pause":
            self.pause()
        if self.command == "-stop":
            self.stop()
        else:
            print "Error\n Use one of these commands to use this programm:\n\
                  '-play'     start playing\n\
                  '-pause'    pause playing\n\
                  '-stop'     stop playing\n\
                  '-next'     play the next song\n\
                  '-previous' play the previous song"

        
a=Player()
a.getcommand()
a.doit()
a.close()
Ich weiß der Code ist nicht perfekt aber es funktioniert =)
Jabber: tayce@jaim.at
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hallo,

mal ein paar Tipps von mir, wie man das Tool verbessern könnte:

Schau Dir mal das optparse-Modul an:
file:///usr/share/doc/python2.5/html/lib/module-optparse.html
Damit kann man ganz einfach Kommandozeilenparameter parsen und nebenbei bekommt man eine "-help"-Ausgabe gratis dazu :-)

Außerdem wären ein paar mehr Kommentare und Leerzeilen zwischen den Methoden ganz nett.
Das Programm würde ich außerdem per

Code: Alles auswählen

if __name__ == "__main__":
    main()
"aufmotzen" :-)

Außerdem würde ich die die doit()-Methode umschreiben und mir die Methoden in einem dict aus dem Parameternamen und den Methoden speichern. Somit verkürzt sich das if-"Monster".

Ansonsten nette Idee :-)
Tayce
User
Beiträge: 56
Registriert: Sonntag 22. April 2007, 18:26
Wohnort: München
Kontaktdaten:

Hyperion hat geschrieben:Außerdem würde ich die die doit()-Methode umschreiben und mir die Methoden in einem dict aus dem Parameternamen und den Methoden speichern. Somit verkürzt sich das if-"Monster".

Ansonsten nette Idee :-)
Hey, ja die Idee mit dem Dict hatte ich grade auch. Naja war gestern tief in der Nacht^^.
Jabber: tayce@jaim.at
BlackJack

Also ich finde da ist *extrem* viel Redundanz in dem Skript. Das ist viel zu lang und umständlich.
Tayce
User
Beiträge: 56
Registriert: Sonntag 22. April 2007, 18:26
Wohnort: München
Kontaktdaten:

Okay, ich hab des gerade mit dem dict versucht aber naja...

Wie schaff ich es das dict mit einer funktion zu verbinden ohne das diese gestartet wird?

ich hatte es in etwa so:

Code: Alles auswählen

dic={"-next":self.client.next(),"-previous":self.client.previous, usw}
dic[self.command]
So würde ich mir auch diese ganzen next() previous() def's sparen aber bei dieser art von dictionary wird anscheinen gleich die funktion gestartet ohne das ich einen aufruf gestartet hab o0
Jabber: tayce@jaim.at
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Ungetested:

Code: Alles auswählen

dic={"-next":self.client.next,"-previous":self.client.previous, usw}
dic[self.command]()
Du darfst halt die Funktion nicht aufrufen, wenn du sie ins Dict packst (dann bindest du den Rueckgabewert an den Value), sondern erst, wenn du sie wieder rausgeholt hast.


Edit: Ungetested :arrow: Immer dieser Wechsel zwischen Deutsch und Englisch, das macht mein Hirn nicht mit... :lol:
Zuletzt geändert von Rebecca am Mittwoch 23. April 2008, 10:20, insgesamt 1-mal geändert.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Tayce hat geschrieben:Okay, ich hab des gerade mit dem dict versucht aber naja...

Wie schaff ich es das dict mit einer funktion zu verbinden ohne das diese gestartet wird?
aus versehen hast du das schon geschafft: lass die klammern weg.

Code: Alles auswählen

def x():
  return 1

d = {
   'ergebnis' : x(), # das resultat des funktionsaufrufes
   'funktion' : x, # das funktionsobjekt selbst
}

print d['funktion']() # so kann man sie dann aufrufen
BlackJack

Eine einfache Lösung ohne Klasse (ungetestet):

Code: Alles auswählen

import sys
import mpd


def main():
    commands = (('play', 'start playing'),
                ('pause', 'pause playing'),
                ('stop', 'stop playing'),
                ('next', 'play the next song'),
                ('previous', 'play the previous song'))
    
    try:
        command = sys.argv[1]
    except IndexError:
        command = None
    
    if command in (c[0] for c in commands):
        client = mpd.MPDClient()
        client.connect('localhost', 6600)
        getattr(client, command)()
        client.close()
    else:
        print 'Use one of these commands:'
        for command, description in commands:
            print '%-10s%s' % (command, description)
Tayce
User
Beiträge: 56
Registriert: Sonntag 22. April 2007, 18:26
Wohnort: München
Kontaktdaten:

Danke Keppla, das wars...

hier mal der Code V 2 ;)

Code: Alles auswählen

#!/usr/bin/env python
import sys
import mpd
class Player(object):
    def __init__(self):
        self.client=mpd.MPDClient()
        self.client.connect("localhost", 6600)

    def getcommand(self):
        try:
            self.command = sys.argv[1]
        except:
            return "Error"

    def doit(self):
        dic={"-next":self.client.next,
                "-previous":self.client.previous,
                "-stop":self.client.stop,
                "-play":self.client.play,
                "-pause":self.client.pause}
        try:
            dic[self.command]()
        except:
            print "Error\n Use one of these commands to use this programm:\n\
                  '-play'     start playing\n\
                  '-pause'    pause playing\n\
                  '-stop'     stop playing\n\
                  '-next'     play the next song\n\
                  '-previous' play the previous song"

def main():
    a=Player()
    a.getcommand()
    a.doit()
    a.close()
if __name__ =="__main__":
    main()
Jabber: tayce@jaim.at
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Ich bin nicht so tief in der POSIX-, GNU- und Sonstwas-Materie, aber Optionen/Schalter in der Form "-foo" erscheinen mir als, naja, ungern geduldet. Vielmehr scheint da die Variante "-f" (kurz) mit "--foo" (lang) gängig zu sein. So kenne und nutze ich das auch vom und mit dem `OptionParser`.

Nachtrag:
Wenn du Kommandos hast, warum verkleidest du die dann als Optionen? Es sind ja essentielle Argumente, also hat der Bindestrich davor eigentlich nichts verloren, sondern ist sogar irreführend.

`.getcommand()` erscheint mir überflüssig. Ich rate dringend, den Kommandonamen von `.doit()` als Parameter entgegen nehmen zu lassen und dorthin `sys.argv[1]` zu übergeben. Dann lohnt sich die Klasse auch schon bald nicht mehr.

Weiterhin schreit dein Code geradezu danach, dass du direkt vom Argument (z.B. "play") mittels `getattr()` nach einer entsprechend benannten Methode des `client`-Objekts suchst.

Spontaner, ungetesteter Versuch:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from os.path import basename
from sys import argv, exit

from mpd import MPDClient


VALID_CMDS = ['start', 'pause', 'stop', 'previous', 'next']

def main():
    try:
        cmd = argv[1]
    except IndexError:
        # Sollte man hier besser auf STDERR schreiben?
        print 'usage: %s <%s>' % (basename(argv[0]), '|'.join(VALID_CMDS))
        exit(2)  # 2 wird oft für Aufruffehler verwendet.

    client = MPDClient()
    client.connect('localhost', 6600)
    getattr(client, cmd)()

if __name__ =="__main__":
    main()
P.S.: OK, ich sehe gerade, im Grunde ist es das, was BlackJack schon demonstriert hat.

Der OptionParser ist manchmal überdimensioniert (Vllt. kommt man da mit dem etwas umständlicheren `getopt` weiter? Oder soll das in absehbarer Zeit aus der Stdlib fliegen?), kann zumindest aber "Usage"-Hilfetexte mit den verfügbaren Optionen erzeugen.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Y0Gi hat geschrieben:Ich bin nicht so tief in der POSIX-, GNU- und Sonstwas-Materie, aber Optionen/Schalter in der Form "-foo" erscheinen mir als, naja, ungern geduldet. Vielmehr scheint da die Variante "-f" (kurz) mit "--foo" (lang) gängig zu sein. So kenne und nutze ich das auch vom und mit dem `OptionParser`.
Ja, ich wollte auch anmeckern, dass das auf GNU-Systemen eher unkonsistent ist. Einige GNU-Programme unterstützen es zwar, aber nur aus historischen Gründen, etwa GNU tar.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Speziell `tar` ist bzgl. CLI-Syntax 'ne ziemliche Katastrophe, finde ich.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Code: Alles auswählen

#!/usr/bin/env python
import sys
from mpd import MPDClient

client = MPDClient()
client.connect('localhost', 6600)
try:
    getattr(client, sys.argv[1])()
except (AttributeError, IndexError):
    print >>sys.stderr client.__doc__
Ich bin pragmatiker ;)
Antworten