Simples MPlayer Frontend

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Drache
User
Beiträge: 51
Registriert: Montag 29. November 2010, 21:51
Wohnort: Berlin
Kontaktdaten:

Hallo Pythoner,

hier ist eine kleine praktische Spielerei von mir:

Code: Alles auswählen

#!/usr/bin/env python
import subprocess,time,threading,os,fcntl
from Tkinter import *
url = 'http://scfire-dtc-aa01.stream.aol.com:80/stream/1048'
cmd = "mplayer , %s" % url
runa = True
print(cmd)
def pastart():
    global p,a
    listbox.insert(0,"Radio wird gestarter")
    p = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE)
    fcntl.fcntl(p.stdout, fcntl.F_SETFL, os.O_NONBLOCK)
    time.sleep(1)
    while runa:
        time.sleep(0.5)
        try:
            a = p.stdout.readline()
            if a[0:3] == 'ICY':
                x,y,z = a.partition(';')
                listbox.insert(0,x[22:])
                main.update
                   
        except:
            main.update

    
    
                    
def pystop():
    runa = False
    print(p)
    p.stdout.close()
    p.kill()

    

def test1():
    global T1
    T1 = threading.Thread(target = pastart)
    T1.start()
    
main = Tk()
main.title('Radio Paradise')
main.minsize(500,400)
main.maxsize(500,400)
btnstart = Button(main,text='Start',command = test1)
btnstart.pack()
btnstop = Button(main,text='Stop',command = pystop)
btnstop.pack()
listbox = Listbox(main,width=60)
listbox.pack()
main.mainloop()
hat jemand lust, ein wenig daran mit rum zu basteln ?
ich bekomms auch nicht auf NT übertragen :
fcntl muss gegen msvcrt ersetzt werden, bekomm ich einfach nicht hin.

Würde mich über Kritik und Hilfe sehr freuen.

Bis bald
Drache
maxi_king_333
User
Beiträge: 110
Registriert: Freitag 25. Dezember 2009, 03:42

Hi,

bin auch noch relativ neu hier, aber was ich bis jetzt so gelernt habe:

Man sollte sich für jeden Import eine Zeile genehmigen und nicht alles mit Kommas in eine Zeile questchen.
Auch * Importe sind eher ungünstig.
Man sollte sich auf ' oder " festlegen und nicht mischen.
Man sollte eindeutige Namen nehmen, sie können auch länger sein.
Also nicht p sondern process.

Dein cmd Argument für subprocess.Popen sollte eine Liste sein.

Code: Alles auswählen

cmd = ['mplayer', url]
Aus dem Komma in deinem CMD-String, werde ich auch nicht so ganz schlau.

Das Keyword global sollte man nicht verwenden.
Du könntest hier eine Klasse erstellen, die die Variablen enthält.

Anstelle stdout auf NONBLOCK zu stellen könntest du dir mal das select-Modul angucken.

Viele Grüße
Maxi
Drache
User
Beiträge: 51
Registriert: Montag 29. November 2010, 21:51
Wohnort: Berlin
Kontaktdaten:

maxi_king_333 hat geschrieben: Man sollte eindeutige Namen nehmen, sie können auch länger sein.
Also nicht p sondern process.
Stimmt
maxi_king_333 hat geschrieben: Dein cmd Argument für subprocess.Popen sollte eine Liste sein.

Code: Alles auswählen

cmd = ['mplayer', url]
Aus dem Komma in deinem CMD-String, werde ich auch nicht so ganz schlau.
Mmmmh, werde ich mal überprüfen, ich weiß auch nicht warum, nur die Variante hat auf Anhieb geklappt hat.
maxi_king_333 hat geschrieben: Das Keyword global sollte man nicht verwenden.
Du könntest hier eine Klasse erstellen, die die Variablen enthält.
Um ehrlich zu sagen, bei einem so kleinen Projekt, finde ich eine kompakten Code besser zu lesen.
maxi_king_333 hat geschrieben: Anstelle stdout auf NONBLOCK zu stellen könntest du dir mal das select-Modul angucken.
Kenn ich nicht, mach ich aber 100 % tig

Vielen Dank
Drache
lunar

@Drache: Die Verwendung von "global" lässt Quelltext weder kompakter noch leichter lesbar werden, erst recht nicht in Deinem Fall. Im Gegenteil, er erschwert das Verständnis eher. In "pystop()" beispielsweise ist die Bedeutung von "p" nicht sofort ersichtlich, man muss den gesamten Quelltext durchsuchen, um die Bedeutung von "p" letztlich durch die Zuweisung in "pastart()" zu erkennen. In "pastart()" wiederum muss man bis ans Ende des Quelltexts springen, um die Bedeutung von "listbox" zu erfahren.

Wäre die Oberfläche in einer Klasse gekapselt, so wäre es aufgrund des vorangehenden "self." sofort klar, wo die Namen herkommen, und es gäbe mit ".__init__()" dann genau einen Ort, an dem man nachschauen müsste.

Versuche, den Quelltext mithilfe einer Klasse neu zu implementieren. Du wirst feststellen, dass der Quelltext nicht umfangreicher wird, sondern im wesentlich leichter zu verstehen ist.

Die Anweisung "main.update" bewirkt in dieser Form gar nichts. Falls das ein Methodenaufruf sein sollte, so fehlen die Klammern am Schluss.

Ein reines "except:" ohne Angabe einer konkreten Ausnahme ist nur selten eine gute Idee. So „versteckst“ Du auch Programmierfehler innerhalb des "try"-Blocks, beispielsweise einen "NameError", der durch einen falsch geschriebenen Namen ausgelöst wird. Gebe nach "except" immer einen konkreten Ausnahmetypen an, um nur die Fehler abzufangen, die Du im aktuellen Kontext auch sinnvoll behandeln kannst. Andernfalls ist es besser, die Ausnahme unbehandelt zu lassen. Das Programm „stürzt“ dann zwar ab, aber mit ausführlichen Informationen, die Dir die Fehlersuche erleichtern.
Drache
User
Beiträge: 51
Registriert: Montag 29. November 2010, 21:51
Wohnort: Berlin
Kontaktdaten:

Hallo lunar,

du hast recht, ich sollte mir die OOP einverleiben.
Der Grund, das ich mich (noch) schwer tu ist,
das aus 10 Zeilen Code locker 30 werden, oder ?.

Die Anweisung main.update oder main.update() / es geht beides
sorgt dafür das die GUI nicht einfriert.
Gerade wenn es ins Internet geht, scheinen Tkinter-Benutzer-Oberflächen
dazu zu neigen,keine Ahnung ob das auch für GTK oder QT gilt.

Beim Auslesen des stdout kommt es häufig vor das die Datei leer ist (EOF)
daher der except:
Steht bei mir auf der Todo- Liste das abzuändern.
Dummerweise hatte ich aus Zeitmangel noch keine Möglichkeit das zu weiter zu verfolgen .

Auch dir vielen Dank
Drache
lunar

@Drache: Es geht nicht beides. Du darfst mir ruhig glauben, wenn ich Dir sage, dass "main.update" nichts bewirkt. Die Klammern sind obligatorisch, es muss "main.update()" heißen. In der aktuellen Implementierung friert die Oberfläche ein, weil "main.update" niemals aufgerufen wird.

Das hat im Übrigens auch nichts mit „Internet“ oder einer magischen „Neigung von Tk-Oberflächen“ zu tun, sondern ist einfach die Folge davon, dass die Hauptschleife, welche die Ereignisse verarbeitet, nicht ausgeführt wird, solange noch blockierende Operationen innerhalb der Hauptschleife laufen. Das ist in jedem GUI-Toolkit so.

Wenn Du von zehn Zeilen auf dreißig kommst, weil Du eine Klasse implementiest, dann ist das Resultat offenbar ebenso wenig optimal. Möglich, dass der Quelltext etwas länger (dafür aber verständlicher) wird, doch sicherlich nicht um das dreifache.
Drache
User
Beiträge: 51
Registriert: Montag 29. November 2010, 21:51
Wohnort: Berlin
Kontaktdaten:

@lunar

Eigentlich wollte ich dir jetzt beweisen durch ein
#main.update
und ein
except:
#main.update
pass

Das ich recht hab, hab ich aber nicht, dumm gelaufen.

Also, es stimmt, was du schreibst.
Mein Irrtum beruht darauf, das es in einem anderen Programm von mir so war.
Dabei ging es um einen anderen Internet Zugriff.

Dank dir
Peter

P.S. die EDV lügt nicht :wink:
Antworten