Programm Kontrolle

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.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Denk doch noch mal bitte über dieses nach - ich erwähnte das ja schon einmal:

Code: Alles auswählen

prog_short = '{}'.format(programm[:15])
Sage mir doch mal, welchen Typen `programm` hat - aus Deinen bisherigen Beiträgen schließe ich, dass es sich bereits um einen String handelt. Damit wäre es doch trivial, wie man das *viel* einfacher formulieren kann! Und wenn es kein String wäre, dann wäre es dennoch sinnvoller, hier `str()` zu nutzen, als umständlich die `format`-Methode für die Konvertierung zu "missbrauchen".

Deine Aufgabe ist also folgendes: Öffne eine Python-Shell und belege mal `programm` (ggf. über Copy & Paste) mit einem realen Wert. Dann Arbeitest Du Dich von "hinten nach vorne" durch Deinen Ausdruck und lässt Dir mal die Teilergebnisse ausgeben. Und Du wirst sehen, wie einfach das gehen kann und wie kompliziert Du es ausgedrückt hast.

Auch hier trifft wieder meine Haupt-"Kritik" zu: Du denkst zu wenig über Code nach!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Nobuddy: Die erste Zeile wurde ja schon angesprochen. Und mindestens ein weiterer Funktionsaufruf ist überflüssig — ich vermute sogar zwei.

`pid_current` würde ich nicht mit 0 vorbelegen. Das ist letztendlich eine gültige Prozess-ID die hier aber verwendet wird um „keine Prozess-ID gefunden” zu symbolisieren. Damit hat dieser Wert eine zweideutige Bedeutung. `None` würde sich hier als Wert anbieten.
Nobuddy
User
Beiträge: 1023
Registriert: Montag 30. Januar 2012, 16:38

@Hyperion, boah ..., bin ich auf der Leitung gestanden, keine Ahnung warum das solange gedauert hat. :K
Dies reicht ja völlig:

Code: Alles auswählen

prog_short = programm[:15]
@BlackJack, das mit 'None' habe ich gemacht.
Nach etlichem Testen habe ich festgestellt, daß alleine mit:

Code: Alles auswählen

for prog in psutil.process_iter():
        if prog.name == prog_short and int(prog.pid) != int(pid_start):
            pid_current = prog.pid
            break
nicht einwandfrei funktioniert.
Ich benötige dies so,

Code: Alles auswählen

    for prog in psutil.process_iter():
        if prog.name != 'python' and prog.name == programm[:15] and int(prog.pid) != int(pid_start):
            pid_current = prog.pid
            print pid_current
            print '----'
            break
        elif programm in psutil.Process(int(prog.pid)).cmdline and int(prog.pid) != int(pid_start):
            pid_current = prog.pid
            print pid_current
            break
        else:
            pid_current = None
damit läuft dies bei mir fehlerfrei.

Manchmal wird bei:

Code: Alles auswählen

for prog in psutil.process_iter():
    print prog.name
nur 'python' und manchmal 'lbestellorder.p' ausgegeben. Somit bekomme ich dann keinen Treffer, weil ja mein Programm 'lbestellorder.py' heißt.
Daher benötige ich noch dies:

Code: Alles auswählen

programm in psutil.Process(int(prog.pid)).cmdline
und erhalte somit die Ausgabe
['python', 'lbestellorder.py']
.
Warum variiert die Ausgabe von 'name' bei Ersterem?
BlackJack

Eigentlich hatte ich mich ja schon rausgehalten weil ich das Gefühl hatte es bringt einfach nichts. Nach dem hier gebe ich dann doch endgültig auf: ``psutil.Process(int(prog.pid)).cmdline``… m(
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Also bei mir sieht die Ausgabe doch ganz vernünftig aus:

Code: Alles auswählen

>>> for prog in psutil.process_iter():
...     print prog, prog.pid, type(prog.pid)
... 
psutil.Process(pid=1, name='init [5]') 1 <type 'int'>
psutil.Process(pid=2, name='kthreadd') 2 <type 'int'>
psutil.Process(pid=3, name='ksoftirqd/0') 3 <type 'int'>
psutil.Process(pid=6, name='migration/0') 6 <type 'int'>
psutil.Process(pid=7, name='watchdog/0') 7 <type 'int'>
psutil.Process(pid=8, name='cpuset') 8 <type 'int'>
psutil.Process(pid=9, name='khelper') 9 <type 'int'>
Wonach suchst Du denn jetzt genau? Ich dachte Du suchst nach der pid!?

Desweiteren schau Dir mal den Typen an, den `Process.pid` liefert! Das erklärt BlackJacks obigen Einwurf bezüglich der unnötigen Funktionsaufrufe...

Der von BlackJack monierte Aufruf ist natürlich der Hammer; hier mal in vier Teile gesplittet zur Herleitung der Sinnlosigkeit:

Code: Alles auswählen

>>> for prog in psutil.process_iter():
...     print prog
...     print prog.pid
...     print psutil.Process(prog.pid)
...     print psutil.Process(prog.pid).cmdline
... 
psutil.Process(pid=1, name='init [5]')
1
psutil.Process(pid=1, name='init [5]')
['init [5]']
psutil.Process(pid=2, name='kthreadd')
2
psutil.Process(pid=2, name='kthreadd')
[]
psutil.Process(pid=3, name='ksoftirqd/0')
3
psutil.Process(pid=3, name='ksoftirqd/0')
[]
Sollte Dir immer noch nicht klar sein, was Du da tust, so schau Dir doch mal das an:

Code: Alles auswählen

>>> psutil.Process(1)
<psutil.Process(pid=1, name='init [5]') at 139923431394256>
Hui... `psutil.Process(pid)` liefert mir also den Prozess zu einer existierenden PID... Du holst Dir die PID aber schon aus einem `Process`-Objekt, welches Du Dir durch den Schleifenkopf "erstellen" lässt. Indem Du also die PID aus einem bestehenden `Process`-Objekt holst und damit ein neues `Process`-Objekt erzeugst, welches *denselben* Prozess repräsentiert, drückst Du folgendes einfach nur in kompliziert aus:

Code: Alles auswählen

prog.cmdline
Man erkennt doch leicht, dass `print prog` und `print psutil.Process(prog.pid)` identisch sind...

... :roll:

Ich habe immerhin schon mal das unnütze `int(...)` weggelassen, was den Ausdruck noch komplizierter macht.

Ich habe mir nicht die komplette "Logik" in den `if`s angeguckt, denke aber mal, dass Du nur stumpf rätst und nicht wirklich sinnvoll Ausdrücke entwickelst.

Hast Du das eigentlich mal in einer Shell ausprobiert? Ich vermute mal, dass Du davon immer noch viel zu selten Gebrauch machst! Wie Du siehst habe ich das alles in einer Shell entwickelt und bin ohne alles übrige an Code auf den Sinn / Unsinn gekommen. Wenn Du Dinge immer nur im "großen" Programm ausprobierst, kommst Du echt nicht zu Potte und verrennst Dich zu sehr - wie man ja mal wieder gesehen hat!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Nobuddy
User
Beiträge: 1023
Registriert: Montag 30. Januar 2012, 16:38

@BlackJack, wußte nicht, daß 'prog.cmdline' auch geht.

Ist dies aktzeptabel?

Code: Alles auswählen

    for prog in psutil.process_iter():
        if programm[:15] in prog.name or programm in prog.cmdline:
            if int(prog.pid) != int(pid_start):
                pid_current = prog.pid
                break
        else:
            pid_current = None
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hast Du mein Posting überlesen? Da steht ja immer noch `int(prog.pid)`... :!:

Der `else`-Zweig ist doch auch wieder unschön:

Code: Alles auswählen

...
else:
    pid_current = None
Du musst `pid_current` *vor* der Schleife an `None` binden; das ist doch viel effizienter, als in *jedem* Durchlauf der Schleife!

Und natürlich "geht" `prog.cmdline` - `prog.pid` "geht" ja auch! Was hast Du denn gedacht, was `prog` für ein Objekt ist? Und wie bist Du auf `prog.pid` gekommen, ohne zu erkennen, dass logischer Weise *alle* Attribute und Properties eines Objekt-Typen auf diesem aufrufbar sind? Auch dies ist (leider) wieder ein Beispiel für Deine Art und Weise, *nicht* richtig / gründlich / ausreichend über Code nachzudenken, den Du schreibst :!:

Ich denke, wenn Du das nicht schnell änderst, dann wirst Du mit mir alleine als Helfer auskommen müssen in naher Zukunft... denn im Moment ist es einfach nur frustrierend zu sehen, dass praktisch *keine* grundlegenden Tipps von Dir umgesetzt werden; damit meine ich Dinge, wie das allgemeine Vorgehen, das Lernen von Grundlagen, das Ausprobieren und Entwickeln von Ausdrücken in einer Shell, usw.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Nobuddy
User
Beiträge: 1023
Registriert: Montag 30. Januar 2012, 16:38

Hallo Hyperion,
Nach meinem Post bin ich gleich auf die nächste Seite geleitet worden, daher habe ich Deinen letzten Post erst jetzt gesehen.
War keine böse Absicht dahinter, Danke für Deinen Hinweis.

Das mit 'pid_current = None' dachte ich auch, daß die Position vorher besser war. Habe mich da irgendwie verunsichern lassen. Das werde ich sofort wieder berichtigen.

So, nun zu Deinem letzten Post.
Die erste Ausgabe sieht gut aus und sehe jetzt auch daß das int-Format 'int(pid_start)' hier unnötig ist.

Ich suche die PID('s), die bei einem evtl. Doppelstart des Programms entstanden sind.

Mit Deinen Erklärungen, vermute ich mal, daß ich schon mit meinem letzten Post richtig lag, JA?
Aktueller Stand:

Code: Alles auswählen

    pid_start = psutil.Process(os.getpid()).pid

    pid_current = None

    for prog in psutil.process_iter():
        if programm[:15] in prog.name or programm in prog.cmdline:
            if prog.pid != pid_start:
                pid_current = prog.pid
                break
Du meinst, ich probiere nur das Programm als Ganzes und nicht einzelne Punkte, da irrst Du Dich.
Ich nehme mir einzelne Zeilen vor und schaue nach der Ausgabe. Ich weiß, daß ich noch zu kompliziert denke, was bei Python eigentlich so nicht sein muß. Vielleicht ein Problem was dazu beiträgt, sind meine Nicht-Englischkenntnisse, sonst wären die englischsprachigen Seiten für mich besser verständlich. Ich versuche englischsprachige Texte mit dem Google-Übersetzter, mir übersetzen zu lassen. Oft ist dies dann so verständlich, daß ich mir einen Reim drauf machen kann. Hier allerdings hat er versagt:
Return an iterator yielding a Process class instances for all running processes on the local machine. This should be preferred over doing for pid in psutil.get_pid_list(): psutil.Process(pid) as it safe from race conditions.
Vielleicht könntest Du mir den zweiten Satz richtig übersetzen?

Ich arbeite mit Geany, dort erhalte ich normale Ausgabe, Fehler-Codes und -Beschreibungen. Manche Dinge probiere ich auch auf der Konsole aus. Ich habe auch ipython, ein Terminal für Python, das habe ich aber bis jetzt selten genutzt.

Es tut mir Leid, daß ich so frustrierend auf Euch wirke. Ich verstehe Euch wirklich, daß dies kein Dauerzustand sein kann viele mich als 'hoffnungslos' abstempeln ...

Ich will keine Versprechungen abgeben, hoffe aber für mich und Euch, daß sich dies bessert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Nobuddy hat geschrieben: Das mit 'pid_current = None' dachte ich auch, daß die Position vorher besser war. Habe mich da irgendwie verunsichern lassen.
Du darfst Dich nicht verunsichern lassen, sondern musst einfach darüber nachdenken. Frage Dich stets: Was passiert hier im Code? Wenn Du eine Schleife hinschreibst, dann frage Dich, "Was passiert in jedem Durchlauf?". Genau an diesem Punkt erkennst Du dann, dass es keinen Sinn macht, bei quasi jedem Durchlauf `pid_current` erneut an `None` zu binden - oder? ;-)

Du bist sicher nicht zu dumm, dieses nachzuvollziehen! Dir fehlt es an der Fähigkeit, Code genau so zu betrachten, wie ich es Dir gerade vorgeführt habe. Und genau daran musst Du arbeiten :-)
Nobuddy hat geschrieben: Hier allerdings hat er versagt:
Return an iterator yielding a Process class instances for all running processes on the local machine. This should be preferred over doing for pid in psutil.get_pid_list(): psutil.Process(pid) as it safe from race conditions.
Vielleicht könntest Du mir den zweiten Satz richtig übersetzen?
Naja, ich versuche es mal - auch wenn mein Englisch nicht gerade perfekt ist ;-)
"Gibt einen Iterator zurück, der ein Exemplar der `Process`-Klasse für alle laufenden Prozesse der lokalen Maschine liefert. Dieses Vorgehen sollte man gegenüber `for pid in psutil.get_pid_list(): psutil.Process(pid)` bevorzugen, da es sicher gegenüber "race conditions" ist.

Du hast den Aufruf an sich aber ja auch richtig "interpretiert".

Ich kapiere aber Deinen ganzen Ansatz noch nicht - hatte deets Dir nicht eine fertige Lib empfohlen, mit der man Lockfiles anlegen kann? Und wenn Du diese nicht verwenden magst, wäre es doch zielführender via `fcntl`-Modul eine Lockdatei zu erstellen...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
deets

Hyperion hat geschrieben: Ich kapiere aber Deinen ganzen Ansatz noch nicht - hatte deets Dir nicht eine fertige Lib empfohlen, mit der man Lockfiles anlegen kann? Und wenn Du diese nicht verwenden magst, wäre es doch zielführender via `fcntl`-Modul eine Lockdatei zu erstellen...
Nobody knows but Nobuddy. Statt 3 Zeilen zu schreiben die das Problem loesen, lieber 3 Wochen fuer 30 Zeilen verbraten, die das Problem *nicht* loesen. Aber jeder nach seiner Fasson...

http://www.youtube.com/watch?v=Ebr6FbCGoTE
Nobuddy
User
Beiträge: 1023
Registriert: Montag 30. Januar 2012, 16:38

Hyperion hat geschrieben: Ich kapiere aber Deinen ganzen Ansatz noch nicht - hatte deets Dir nicht eine fertige Lib empfohlen, mit der man Lockfiles anlegen kann? Und wenn Du diese nicht verwenden magst, wäre es doch zielführender via `fcntl`-Modul eine Lockdatei zu erstellen...
Wahrscheinlich war ich zu arg auf mein Vorhaben fixiert, so daß ich vor lauter Wald, keine Bäume mehr sah. :wink:
deets hat geschrieben:Nobody knows but Nobuddy. Statt 3 Zeilen zu schreiben die das Problem loesen, lieber 3 Wochen fuer 30 Zeilen verbraten, die das Problem *nicht* loesen. Aber jeder nach seiner Fasson...
Ja, das ist oft mein Problem. Ich will wirklich versuchen, von meiner Kompliziertheit weg zukommen, das Leben könnte ja dann so einfach sein ... :wink:

Das mit dem `fcntl`-Modul, dürfte wohl tatsächlich die einfachste Lösung sein, muß mich da nur nochmal durchlesen!

Die fertige Lib, war mir zu kompliziert, damein Englisch .... :K
deets

Nobuddy hat geschrieben:
Das mit dem `fcntl`-Modul, dürfte wohl tatsächlich die einfachste Lösung sein, muß mich da nur nochmal durchlesen!

Die fertige Lib, war mir zu kompliziert, damein Englisch .... :K
Nee, is klar. Das fcntl Modul (mit englischer Dokumentation) welches ein ziemlich tiefes Verstaendnis von den beteiligten Systemcalls verlangt vs. ein Modul, das dir das in 3 Zeilen wegabstrahiert + sogar Beispielcode in den Tests hat, den ich verlinkt habe....

Dir ist nicht zu helfen.
Nobuddy
User
Beiträge: 1023
Registriert: Montag 30. Januar 2012, 16:38

@deets, anhand dieses Links http://aktuell.de.selfhtml.org/artikel/ ... python.htm, sieht das nicht ganz so kompliziert aus, aber ich kann mich auch täuschen.

Es wurde hier in diesem Thread schon sehr viel, vielleicht auch schon zu viel geschrieben, so daß ich mich nur noch entfernt an diese Lib erinnere ...

Es gibt i.d.R. immer mehrere Möglichkeiten Dinge umzusetzen und vieles sieht man oft zu kompliziert, wie auch bei mir.
Es ist ein Lernprozess, der beim Einen schneller und beim Anderen eben langsamer voran geht.
Fehler vermeiden bringt nur die Praxis und Erfahrung, die man in so einem Prozess durch schreitet.
Toleranz bringt den Vorteil, andere auch Fehler machen zu lassen, auch das gehört zum Lernprozess für beide, der was lernen und der der etwas weitergeben möchte. :wink:
deets

Nobuddy hat geschrieben:@deets, anhand dieses Links http://aktuell.de.selfhtml.org/artikel/ ... python.htm, sieht das nicht ganz so kompliziert aus, aber ich kann mich auch täuschen.
Ich wuerde mal sagen angesichts deiner bisherigen Schwierigkeiten - ja, da taueschst du dich. Und in jedem Fall ist es komplizierter als die abl.util.LockFile-Variante. Die ist ja genau deswegen geschrieben worde, um den OS-abhaengigen und je nach Anwendungsfall unterschiedlichen Einsatz des fcntl-Moduls zu abstrahieren...

Es wurde hier in diesem Thread schon sehr viel, vielleicht auch schon zu viel geschrieben, so daß ich mich nur noch entfernt an diese Lib erinnere ...
Das kann ja gut sein. Dann wundere ich mich aber, wieso du sagst "Die fertige Lib war mir zu kompliziert". Wo du dich doch ganz entfernt erinnern kannst?!?
Es ist ein Lernprozess, der beim Einen schneller und beim Anderen eben langsamer voran geht.
Fehler vermeiden bringt nur die Praxis und Erfahrung, die man in so einem Prozess durch schreitet.
Toleranz bringt den Vorteil, andere auch Fehler machen zu lassen, auch das gehört zum Lernprozess für beide, der was lernen und der der etwas weitergeben möchte. :wink:
Es gibt einen Unterschied zwischen einem Lernprozess, und dem ignorieren von Rat. Niemand hindert dich daran, alles selbst zu machen. Stellt sich dann die Frage, *warum* du dann hier um Rat fragst. Weil du dir doch vielleicht aus den Erfahrungen anderer schneller Erfolg beim eigenen Lernen versprichst? Wieso ignorierst du dann aber willkuerlich was man dir vorschlaegt? Wenn du die Erfahrung haettest, die dargebotenen Ansaetze zu vergleichen und nach informierten Kriterien abzulehnen wuerdest du die Fragen wahrscheinlich erst gar nicht stellen.... so aber zeigt sich Willkuer oder Ignoranz. Ich unterstelle dir da keine Boshaftigkeit. Nur fragwuerdige Beliebigkeit in deinem Vorgehen.
Nobuddy
User
Beiträge: 1023
Registriert: Montag 30. Januar 2012, 16:38

@deets, ich wollte Dich keinesfalls irgendwie angreifen.
Willkuer oder Ignoranz sind schon harte Worte, hoffe daß ich Dich irgendwann vom Gegenteil überzeugen kann. :wink:
deets

Nobuddy hat geschrieben:@deets, ich wollte Dich keinesfalls irgendwie angreifen.
Willkuer oder Ignoranz sind schon harte Worte, hoffe daß ich Dich irgendwann vom Gegenteil überzeugen kann. :wink:
Nix einfacher als das - folge einfach mal den Ratschlägen von mir & anderen hier, die dir schon vor X Seiten gegeben wurden. Anstatt dich in andere Dinge zu verbeißen und noch eine extrarunde zu drehen...
Nobuddy
User
Beiträge: 1023
Registriert: Montag 30. Januar 2012, 16:38

@deets, daran werde ich arbeiten.

Zu 'fcntl', habe ich folgendes am Anfang des Programms erstellt:

Code: Alles auswählen

PROGRAMM = 'lbestellorder.py'

# Programm wird bei zweitem Starten des Programms gesperrt.
# Mehrfachstart wird verhindert
f = open(PROGRAMM, "r+")
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
Funktioniert prima, ein Mehrfachstart ist so nicht mehr möglich (nach meinen Testś).

Was nicht funktioniert ist, wenn ich dies in eine Funktion packe:

Code: Alles auswählen

PROGRAMM = 'lbestellorder.py'

def prog_barrier(PROGRAMM):
    # Programm wird bei zweitem Starten des Programms gesperrt.
    # Mehrfachstart wird verhindert
    f = open(PROGRAMM, "r+")
    fcntl.flock(f.fileno(), fcntl.LOCK_EX)

prog_barrier(PROGRAMM)
Da Du angesprochen hast, daß dies nicht so einfach ist, wie es aussieht, würde ich mich über ein Info über die 'versteckten' Gefahren bzw. Probleme freuen.

Das mit der Lib werde ich mir nochmals genauer anschauen.
Nobuddy
User
Beiträge: 1023
Registriert: Montag 30. Januar 2012, 16:38

fcntl funktioniert soweit, daß es das betreffende Programm dann sperrt, sehe aber inzwischen die ein:
deets hat geschrieben: Ich wuerde mal sagen angesichts deiner bisherigen Schwierigkeiten - ja, da taueschst du dich. Und in jedem Fall ist es komplizierter als die abl.util.LockFile-Variante. Die ist ja genau deswegen geschrieben worde, um den OS-abhaengigen und je nach Anwendungsfall unterschiedlichen Einsatz des fcntl-Moduls zu abstrahieren...
Also wenn, dann doch die Lib ... :wink:
Nobuddy
User
Beiträge: 1023
Registriert: Montag 30. Januar 2012, 16:38

So, habe mir von hier http://hg.ableton.com/abl.util/src/07b1 ... ockfile.py, den kompletten Ordner 'abl.util' abgespeichert.

Wie gehe ich jetzt weiter vor?
deets

das war falsch. du musst das ding so installieren wie andere 3rd-party-packages auch - via easy_install oder pip zb. psutil hast du doch auch irgendwie installiert bekommen, analog dazu.
Antworten