CPU-Auslastung bei laufendem Skript

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.
Antworten
zac
User
Beiträge: 7
Registriert: Dienstag 12. Mai 2015, 20:12

Hallo,

bei folgenden Programm hat der Raspi eine CPU-Auslastung von 100%. Was kann man anders machen bzw. besser machen um die CPU zu schonen? Mein Ziel ist, die Volume des MPD auf 3% zu setzen, sobald keine Musik mehr läuft.

Code: Alles auswählen

#!/usr/bin/python3

from mpd import * 

client = MPDClient();

client.connect("localhost", 6600)

while 1:
 clientstate = client.status()
 if clientstate['state'] == "stop":
  client.setvol(3)
	

client.close() # send the close command
client.disconnect()
Benutzeravatar
/me
User
Beiträge: 3554
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Dein Code rennt einfach permanent durch die while-Schleife. Die Schleife wird auch niemals verlassen, so dass close und disconnect nie erreicht werden.

Du könntest innerhalb der Schleife ein kleines sleep einbauen um die Auslastung zu reduzieren und du solltest dir überlegen unter welchen Umständen du die Schleife vielleicht doch verlassen möchtest.
zac
User
Beiträge: 7
Registriert: Dienstag 12. Mai 2015, 20:12

Naja verlassen will ich ja nicht wirklich. Muss etwas anders an die Sache herangehen.
Wahrscheinlich besser, wenn ich erst in die while-schleife springe, wenn Musik läuft also der status "play" ist.
BlackJack

@zac: Das macht keinen Sinn denn egal welcher Status gerade aktiv ist musst Du ja überwachen ob er sich ändert. Neben dem `sleep()` damit das nicht 100% frisst könntest Du es auch unterlassen im Stopzustand ständig die Lautstärke zu setzen. Es reicht ja das nur einmal zu tun wenn sich der Zustand zu „stop“ ändert.

Noch besser wäre natürlich wenn Du gar nicht erst so eine „busy waiting“-Schleife benutzt sondern Dich informieren lässt wenn sich der Zustand verändert hat. Das wäre dann letztendlich warten auf eingehende Daten über eine Socketverbindung was so gut wie gar keine CPU-Zeit verbraucht.

Wenn Du die Schleife nicht verlassen willst, dann macht es keinen Sinn den Code danach zu schreiben. Zumindest nicht *so* Der müsste dann in einen ``finally:``-Block damit er ausgeführt wird fall zum Beispiel der Benutzer den Code mit Strg+C abbricht.

Nebenbei: Sternchen-Importe sind Böse™. In Python braucht man kein Semikolon um Anweisungen abzuschliessen. Es gibt einen Wahrheitstype `bool` mit den Werten `True` und `False` und die sollte man verwenden und keine Zahlen. Einrückung ist per Konvention vier Leerzeichen pro Ebene.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@zac: das Paket hat genau die Funktion schon eingebaut, die Du brauchst: MPDClient.idle wartet bis sich etwas tut.
zac
User
Beiträge: 7
Registriert: Dienstag 12. Mai 2015, 20:12

Sirius3 hat geschrieben:@zac: das Paket hat genau die Funktion schon eingebaut, die Du brauchst: MPDClient.idle wartet bis sich etwas tut.
Vielen Dank für den Hinweis - hab ich irgendwie übersehen :roll: :oops:
Habe es jetzt so gelöst:

Code: Alles auswählen

#!/usr/bin/python3

from mpd import * 

# Init
client = MPDClient()
client.connect("localhost", 6600)


while True:

 status_changed = client.idle() 
 if status_changed[0] == "player":
  clientstate = client.status()

  if clientstate['state'] == "stop":
   client.setvol(3)
	
# Closing 
client.close() 
client.disconnect()
Auslastung bei ~ 14%. Der Code lässt sich bestimmt schöner gestalten, aber es tut das was es soll...

/zac
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

zac hat geschrieben: Auslastung bei ~ 14%. Der Code lässt sich bestimmt schöner gestalten, aber es tut das was es soll...
Also zum einen könntest (und solltest!) Du *vier* Spaces als Einrückungstiefe wählen - das ist eine Konvention, die PEP8 regelt.

Zum anderen bezweifel ich, dass der Code wirklich tut, was *Du* willst. Ab Zeile 19 wird 's nämlich unsinnig. Der Code wird *niemals* erreicht werden, weil Du davor eine Endlosschleife hast, die *niemals* verlassen wird.

Du kannst die Zeilen also weglassen, oder irgend wie eine Abbruchbedingung und dann ein ``break`` in die Schleife einbauen. (Und den Kommentar "closing" kannst Du getrost weglassen - der enthält keinen Mehrwert gegenüber den folgenden Zeilen, die klar beschreiben, dass da etwas geschlossen wird ;-) )

Ach ja, Sternchen-Import sollte man unterlassen. Importiere einfach ``mpd`` als ganzes oder eben die gezielten Komponenten via ``from mpd import foo, bar # usw...``
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
zac
User
Beiträge: 7
Registriert: Dienstag 12. Mai 2015, 20:12

Hyperion hat geschrieben: Zum anderen bezweifel ich, dass der Code wirklich tut, was *Du* willst. Ab Zeile 19 wird 's nämlich unsinnig. Der Code wird *niemals* erreicht werden, weil Du davor eine Endlosschleife hast, die *niemals* verlassen wird.
Du kannst die Zeilen also weglassen, oder irgend wie eine Abbruchbedingung und dann ein ``break`` in die Schleife einbauen.
Wollte hier noch einbauen, dass bei Shutdown des Systems alles ordentlich geschlossen wird.

Also soweit macht schon, dass was ich will. Bei Stop die Volume auf "3" setzten. Allerdings würde ich das gerne beim Hochfahren automatisch starten. Habe dazu folgenden Eintrag in der Crontrab:

Code: Alles auswählen

@reboot python /home/pi/python-mpd2/vol.py &
Doch es startet nicht. Starte ich es per Hand aus dem Ordner läuft es:

Code: Alles auswählen

pi@raspberrypi ~ $ cd python-mpd2
pi@raspberrypi ~/python-mpd2 $ sudo python vol.py &
[1] 2580
pi@raspberrypi ~/python-mpd2 $
Versuche ich es allerdings aus dem Home-Ordner klappt es nicht:

Code: Alles auswählen

pi@raspberrypi ~ $ sudo python /python-mpd2/vol.py &
[1] 2539
pi@raspberrypi ~ $ python: can't open file '/python-mpd2/vol.py': [Errno 2] No such file or directory

[1]+  Exit 2                  sudo python /python-mpd2/vol.py

pi@raspberrypi ~ $ ls
build  Desktop  mpd.pyc  mpd.py.save  ocr_pi.png  python_games  python-mpd2
Liegt es an einer fehlerhaften Installation des MPD-Moduls, Pyhton oder evtl. ganz woanders?

/zac
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Schonmal überlegt dass das was in der Fehlermeldung steht wahr sein könnte und du den falschen Pfad angibst?
zac
User
Beiträge: 7
Registriert: Dienstag 12. Mai 2015, 20:12

Ja durchaus, diese Fehlermeldung hab ich soweit schon verstanden. Aber wenn ich händisch in das Verzeichnis /python-mpd2 navigiere und starte geht es und in der crontrab mit Pfad-Angabe - wie zu sehen - eben nicht.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Du navigierst nicht nach /python-mpd2 sondern nach ~/python-mpd2.
zac
User
Beiträge: 7
Registriert: Dienstag 12. Mai 2015, 20:12

dachte eigentlich das "~" ist das Zeichen für das Home-Verzeichnis des Users Pi und das "$" gehört doch ebenfalls standardmäßig zur Shell. Oder täusche ich mich da?

/zac
BlackJack

@zac: Soweit ja alles richtig aber in Deinem Heimatverzeichnis ein ``cd python-mpd2`` führt zu einem anderen Verzeichnis Arbeitsverzeichnis als ein ``sudo python /python-mpd2/vol.py`` in dem Heimatverzeichnis aufzurufen. Das ist sogar doppelt falsch: 1. ändert es das Arbeitsverzeichnis nicht und 2. liegt Dein Skript ja offenbar nicht in ``/python-mpd2/vol.py`` sondern in ``~/python-mpd2/vol.py`` wenn Du es als Benutzer ausführt, also wahrscheinlich ``/home/pi/python-mpd2/vol.py``. In der crontab solltest Du den ganzen Pfad angeben. Und/oder falls das Arbeitsverzeichnis wichtig ist, vorher dort mit ``cd`` hinwechseln.
zac
User
Beiträge: 7
Registriert: Dienstag 12. Mai 2015, 20:12

@BlackJack: das mit den Pfaden verstehe ich so halb. Ist er nur ein Verweis? Also zeigt mir "python-mpd2" woanders hin?

Ich habe jetzt in der crontab sämtliche Möglichkeiten ausprobiert. Habe auch den ganzen Ordner unter root kopiert und versucht
mit

Code: Alles auswählen

@reboot python /root/python-mpd2/vol.py &
zu starten. Leider auch ohne Erfolg. Wie sieht denn hier die korrekte Pfadangabe aus?

Habe dann auch zu Python allgemein eine Frage. Ich habe mit die Library in den Ordner "python-mpd2" geladen. Hab ich mein Programm nicht in diesem Ordner, kann Python die Abhängigkeiten zu MPDClient() ja nicht auflösen. Kann ich das umgehen, so dass
es egal ist, wo Library und Programm liegen?

/Zac
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

zac hat geschrieben:@BlackJack: das mit den Pfaden verstehe ich so halb. Ist er nur ein Verweis? Also zeigt mir "python-mpd2" woanders hin?
/python-mpd2 ist der python-mpd2-Ordner in der Wurzel deines Dateisystems, wo sie vermutlich nicht liegt. Das ist da wo /dev, /usr, /home etc. liegen.

~/python-mpd2 ist /home/pi/python-mpd2, also ein Unterordner von deinem Home-Ordner, ergo ein anderer Ort.

Welcher für dich stimmt? Das hängt ab wo es bei dir liegt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten