Problem mit einer Schleife

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
firstfacility
User
Beiträge: 28
Registriert: Samstag 20. Dezember 2014, 09:26

Hallo Leute,

ich habe ein Problem mit einer Schleife. Es geht dabei um einen Airplayer für den Rapi bei dem ich beim Streamen Cover Interpret usw anzeigen lassen möchte. Hierzu wird vom Programm eine Stream-Datei die bei nicht Gebrauch leer ist. Streame ich nun Musik wird mir das passende Cover in ein Verzeichnis geladen welches ich anzeigen lassen möchte, weiterhin steht in der Stream-Datei auch der Cover Name im Format cover-12345wertzu.jpg. Nun hole ich mir den Filenamen aus der Datei um ihn in eine variabel zu packen um das Cover anzuzeigen. Das läuft auch soweit, jedoch benötige ich eine Schleife die je nach Titel die Cover ändert. Also Stream-Datei leer kein Cover Titel 1 Cover1 ein > Titel 2 Cover1 löschen Cover 2 ein usw...

Code: Alles auswählen

.
.
try:
   while True:
      f = open( sys.path[0] + "/now_playing", "r" )
      line1 = f.readline()
      line2 = f.readline()
      line3 = f.readline()
      line4 = f.readline()
      inter = line1[7:]
      titel = line2[6:]
      alb = line3[6:]
      cover = line4[8:]
      newcover = cover
      while cover == newcover:
         os.system("killall xli")
         sleep (1)
         print (cover)
         os.system("xli -quiet -display :1 -title Airplay -geometry +0+200 %s > /dev/null &" % c
over)
        else:
           os.system("killall xli") 
Also bis " cover = line4[8:] " geht noch alles aber die Schleife geht leider gar nicht. Was mache ich falsch, kann mir jemand bei dem Problem helfen ?

Gruß

Frank
Zuletzt geändert von Anonymous am Samstag 29. August 2015, 22:53, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Die Einrückung ist falsch, möglicherweise ein Kopieren und Einfügen-Fehler.

Mal eine blöde Frage: Wo wird in der 2. while-Schleife mal das Cover geändert? Ohne den Code jetzt zu testen, denke ich, dass das Programm in der 2. Schleife hängen bleibt und dort nicht herauskommt.

Du könntest mal bitte einen Datensatz posten, den Du da lädst und Du könntest mal die Ausgabe in der Konsole posten. Ich denke, dass letztere bedingt durch "print (cover)" fortlaufend den gleichen Link printed!?

PS Ich habe keine Raspi-Erfahrung, kann also mit den os.system-Anweisungen nichts anfangen.
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Im Kern lese ich dort als Quellcode:

Code: Alles auswählen

while True:
    print("Ich lade...")
    cover = "Test-Cover"
    newcover = cover
    while cover == newcover:
        print (cover)
In der Konsole liefert es bei mir:

Code: Alles auswählen

>>> 
Ich lade...
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
Test-Cover
...
Ich denke, Du hast dort eine Endlosschleife gebaut. Wenn Du da nicht mit einer der os.system-Anweisungen herauskommst, dann müsstest Du da noch irgendwie einbauen, dass das Programm zu einem anderen Titel wechselt und entsprechend ein anderes Cover lädt.
firstfacility
User
Beiträge: 28
Registriert: Samstag 20. Dezember 2014, 09:26

ich füge die Ausgabe an:

Code: Alles auswählen

xli: Kein Prozess gefunden
artist=Annie Lennox

title=When Tomorrow Comes

album=Eurythmics Greatest Hits

cover-26f95fb9601ef22dede8febb4d178a19.jpg
Ich habe mein Script vorher mit den Print befehlen erweitert, so dass die Ausgabe Zeile 1-3 so in meiner Stream Datei abgelegt werden. Die Zeile 4 ist von mir schon gekürzt worden, weil die Cover Datei genau so im Verzeichnis liegt. Ich füge sie als Variabel in os.system xli ( Viewer ) ein und lasse das Cover auf meinem Xserver ausgeben.
Wie du sehen kannst ist der Killall xli erst mal ins leere gelaufen. Meine Überlegung war halt bei jedem neuen Daternsatz Killall xli und dann xli Cover.jpg auszuführen.

Aber du hast vollkommen recht die zweite Schleife geht nicht mir wird zwar ein Cover angezeigt aber das war es auch dann.
firstfacility
User
Beiträge: 28
Registriert: Samstag 20. Dezember 2014, 09:26

ja genau die Schleife läuft endlos .....
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Naja, ich kann weder etwas zum Raspi noch zum X-Server sagen, weil ich damit nicht arbeite.

Code: Alles auswählen

import os
while True:
    # Definiere eine Abbruchbedingung!

    files = os.listdir()

    for file in files:

        print("Ich zeige das Cover.")
        print("Ich nenne den Interpreten.")
        print("Ich spiele das Lied.")

        print(file)

        input(">>> Weiter...")
Versuch mal diesen Quellcode bei Dir. Die input-Anweisung habe ich eingefügt, weil es sonst durchrauscht. Wenn bei Dir statt der print-Anweisung das Lied gespielt wird, dann bleibt das Cover schon mal stehen.

Persönlich (Geschmackssache!?) würde ich erst einmal alle Daten laden und in eine geeignete Datenstruktur packen, d. h. entweder Dictonary oder eben Liste. Gefühlt im konkreten Fall eine nach dem Interpreteten-Liedtitel-sortierte verschachtelte Liste, weil ich mit Duplikaten rechne. Wenn ich diese Datenstruktur aufgebaut habe, dann würde ich sie entweder mit einer for- oder einer while-Schleife durchlaufen.

Verstehst Du, was ich meine!?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ach _das_ ist dein Problem? Na dann solltest du irgendwann `cover` oder `newcover` in der innersten Schleife aendern.
firstfacility
User
Beiträge: 28
Registriert: Samstag 20. Dezember 2014, 09:26

Meine Stream-Datei ist leer wenn ich keine Lieder abspiele. Erst wenn ich das erste Lied streame erscheint ein Eintrag in der Form des Outputs die ich eben angefügt habe. Ich lade mir den Inhalt Zeilenweise und bearbeite sie und gebe sie später aus.
Meine bearbeitete Zeile zum Cover ist die variable "cover" damit starte ich meinen Viewer "os.system xli cover" Das läuft auch soweit, auch die erste Schleife liefert mir die aktuellen Inhalte der Streaming Datei wenn sich das Lied ändert. Also :
Lied 1 cover-1234567asdfgh.jpg > "cover"
Lied 2 cover-3455960sjdfgöf.jpg > "cover"
usw.

Das Problem ist das ich nach Lied 1 mit "os.system Killall xli" das alte Cover schließe und mit "os.system xli "cover" das neue Bild laden muss. Zum Schluss wenn kein Lied mehr da ist eben nur beenden.

Ich habe in der zweiten Scheife ein Problem mit dem Wert der Variable "cover" da steht keine 1 oder 0, sondern eben cover-123455jhdhffk.jpg. Und damit kann ich nicht umgehen.
Ich habe versucht mit mycover eine zusätzliche Variabel zu schaffen also:
Es wird kein Lied gespielt cover und mycover leer > mache nichts
Es wird das erste Lied gespielt cover hat einen wert mycover aber keinen > lade os.system xli cover
Es wird das zweite Lied gespielt cover eins hat einen Wert mycover hat einen wert > lösche altes cover os.system killall xli und lade neues cover os.system xli cover ....usw

Aber leider lüft das alles nicht die zweite Scheife ist murx..
BlackJack

@firstfacility: Von `mycover` steht da nirgends etwas. Und wozu gehört bitte das ``else``? Das ist falsch eingerückt. Und da fehlt irgendwie ein ``if`` zu, oder? Denn zum ``while`` sollte da sicher nicht gehören denn der Schleifenkörper enthält kein ``break``. Aber vielleicht sollte das ``while`` auch ein ``if`` sein‽ Da dorekt davor ``newcover = cover`` steht macht aber auch ein ``if`` an der Stelle keinen Sinn denn dann gilt natürlich *immer* ``newcover == cover``.
firstfacility
User
Beiträge: 28
Registriert: Samstag 20. Dezember 2014, 09:26

ja du hast recht mycover = newcover, ich habe mit if und while inzwischen so viel probiert das ich nicht darauf geachtet habe weil die Scheife nicht läuft.
firstfacility
User
Beiträge: 28
Registriert: Samstag 20. Dezember 2014, 09:26

Code: Alles auswählen

      if cover != newcover:
         os.system("killall xli")
         sleep (1)
         os.system("xli -quiet -display :1 -title Airplay -geometry +0+200 %s > /dev/null &" % c
over)
         cover == newcover
Wenn ich richtig verstanden hab müsste der erste Teil dann so aussehen ?

Es wird kein Lied gespielt cover und newcover sind gleich es passiert nichts
Es wird Lied 1 gespielt cover hat einen wert newcover keinen es werden die beiden os.system Dinge abgearbeitet. ...
Dann wird der wert von cover in newcover geschrieben und erst bei Lied zwei geht's von vorne los
Ist das der richtige Ansatz ?
firstfacility
User
Beiträge: 28
Registriert: Samstag 20. Dezember 2014, 09:26

Nach einigen Versuchen geht es so nicht. ich sollte mit dem Text arbeiten den aus meiner stream-Datei auslese. Ich sollte so etwas wie "if cover == "jpg":" machen. Aus der Line eine Ausgabe von print (cover) "jpg" zu bekommen geht schon. Aber ich kann nicht damit arbeiten. Wie kann ich den "Text" in einen str oder wert ändern damit ein "if cover == "jpg":" läuft ?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ich denke du solltest einen Schritt zurueck machen und (nochmal) ein Python Tutorial durcharbeiten.

Code: Alles auswählen

cover == newcover
Das ist ein Vergleich, abseits von dem Ergebnis hat der Ausdruck keine Bedeutung und das Ergebnis bleibt ungenutzt.

Von `os.system` solltest du die Finger lassen und stattdessen `subprocess` benutzen, damit kannst du dann auch gleich die Prozess Objekte sammeln und gezielt beenden statt mit der Holzhammer Methode auch unbeteiligte Prozesse zu erwischen.

Fuer das neueste Problem gibt es String Methoden, bspw `endswith`:

Code: Alles auswählen

In [1]: 'cover.jpg'.endswith('.jpg')
Out[1]: True

In [2]: 'cover.png'.endswith('.jpg')
Out[2]: False
Oder eben `os.path.splitext`.
BlackJack

@firstfacility: Ich würde das Problem in kleinere Teilprobleme aufteilen. Zum Beispiel eine Funktion die die Daten für das aktuell gespielte Lied ausliest und ein Wörterbuch mit diesen Informationen liefert. Und falls kein Lied gespielt wird ist das Wörterbuch leer. Darauf lässt sich ganz einfach prüfen, denn ein leeres Wörterbuch ist im boole'schen Kontext ”falsch”.

Dann merkst Du Dir noch das Ergebnis von einem `subprocess.Popen()`-Aufruf vom letzten Bild anzeigen beziehungsweise `None` wenn gerade kein externer Prozess läuft, und schon ist das viel einfacher zu lösen.
firstfacility
User
Beiträge: 28
Registriert: Samstag 20. Dezember 2014, 09:26

Vielen Dank für eure Hilfe, der Tipp mit dem 'cover.jpg'.endswith('.jpg') war super genau das war es ! Somit kann ich zumindest damit arbeiten.
Das mit dem subprocess macht Sinn, nur werde ich mich da wohl erst mal etwas einlesen müssen. Ich arbeite das mal ab ich melde mich dann wegen der Schleife nochmal :-)
firstfacility
User
Beiträge: 28
Registriert: Samstag 20. Dezember 2014, 09:26

Es stellt sich gerade ein Problem beim lesen der Streaming-Datei. Auf der Shell mit cat Streaming-Datei bekomme ich zuverlässig zB:

Code: Alles auswählen

artist=James Blunt
title=One Of The Brightest Stars
album=All The Lost Souls
artwork=cover-ccdc4ae7dbfbe2e188d009db095c1db4.jpg
genre=Rock
comment=
Wenn ich nun aber mit meinem Script :

Code: Alles auswählen

try:
   while True:
      f = open( sys.path[0] + "/now_playing", "r" )
      line1 = f.readline()
      line2 = f.readline()
      line3 = f.readline()
      line4 = f.readline()
      sleep (1)
      f.close()
      inter = line1[7:]
      titel = line2[6:]
      alb = line3[6:]
      cover = line4[8:]
      cover = cover.rstrip('\n')
      fout = open( sys.path[0] + "/command", "w" )
      fout.write(cover)
      fout.close()
      print (cover)
bekomme ich ab und zu eine zerstückelte Ausgabe wie zb:

Code: Alles auswählen

genre=Rock
comment=

=
=
=
=
Wie könnte ich das ändern ?
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Ich würde mich da Stück für Stück dran tasten.
Dateien öffnet man mit "with", damit man sich nicht selbst um das Schließen kümmern muss.

ungetestet:

Code: Alles auswählen

with open(os.path.join(sys.path[0], "now_playing")) as input_file:
    for line in input_file:
        print line
Die Ausgabe müsste identisch mit der von cat sein.

Außerdem möchtest du keine Variablen durchnummerieren sondern stattdessen einen Liste nehmen, oder eine geeignete Datenstruktur für die zu erwartenden Daten. In deinem Fall könnte sich ein dict aufdrängen.

Du musst die Zeilen auch nicht per Hand zerlegen. Dafür gibt es split. Dem kann man auch die Anzahl der maximalen Teile mitgeben, um zu verhindern, dass es zu Fehlinterpretationen kommt, wenn nach dem Trennzeichen noch einmal das Trennzeichen auftaucht:

Code: Alles auswählen

>>> "schluessel=wert".split("=")
['schluessel', 'wert']
>>> "schluessel=wert=irgendwas".split("=", 1)
['schluessel', 'wert=irgendwas']


Die Sache mit dem Warten vor dem Schließen der Datei verstehe ich nicht.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

sparrow hat geschrieben:Die Sache mit dem Warten vor dem Schließen der Datei verstehe ich nicht.
So wie ich das sehe, ändert sich der Inhalt der Datei, sobald ein neuer Titel gespielt wird. Eleganter wäre es natürlich zu testen, ob die Datei seit dem letzten Lesevorgang geändert wurde, bevor sie neu eingelesen wird.
firstfacility
User
Beiträge: 28
Registriert: Samstag 20. Dezember 2014, 09:26

Die Streaming Datei verhält sich nicht wie zB ein Logfile dh die neuen Daten werden nicht nacheinander geschrieben sondern die Datei wird immer wieder neu geschrieben. Ich werde jetzt mal den Vorschlag von sparrow versuchen, das liest sich logisch was er schreibt.
BlackJack

Man könnte dann auch die Datei in einem Rutsch einlesen und dann erst im Speicher in Zeilen zerlegen um die Gefahr zu verringern eine noch nicht vollständig geschriebene neue Datei zu lesen falls der Schreiber die Datei nicht atomar durch eine neue Version ersetzt.

Die Zerlegung an festen Indexwerten pro Zeile sieht mir auf jeden Fall viel zu wackelig aus, da würde ich auch eher allgemein Schlüssel/Wert-Paare parsen und in einem Wörterbuch ablegen. Und das dann in einer Funktion erledigen.

``sys.path[0]`` ist auch ziemlich eigenartig. Was da geneu steht ist von mehreren Faktoren abhängig die man nicht wirklich 100%ig unter Kontrolle hat. Es sei denn man hat dort vorher selber einen Pfad eingefügt, aber dann hat man den ja auch irgendwie anders zur Verfügung als ausgerechnen die erste Position der Pfade für Modulimporte zu verwenden. Pfadteile sollte man mit `os.path.join()` zusammensetzen.
Antworten