subprocess -> wann beendet?

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.
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

subprocess -> wann beendet?

Beitragvon droptix » Mittwoch 16. April 2008, 12:17

Ich starte ein Kommando mittels:

Code: Alles auswählen

process = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)


Ich möchte einen Timeout festlegen, um den Sub-Prozess ggf. automatisch zu beenden, wenn er z.B. nach 15 Sekunden nicht "antwortet". Wie aber kann ich erkennen, ob der Sub-Prozess fertig ist, also beendet wurde? Habe es mit dem `returncode` versucht, aber es gibt ja durchaus Kommandos (z.B. `dir` unter Windows oder `ls` unter Linux), die keinen Returnwert liefern. Dann gibt es da noch die `poll()` Funktion, aber die reagiert auch nicht unbedingt... die Dokumentation verschweigt da vllt. ein paar wichtige Details.

Kann mir wer unter die Arme greifen?
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Beitragvon sma » Mittwoch 16. April 2008, 12:27

Die von dir verlinkte Doku sagt doch, dass `returncode`ein `None` liefert, wenn der Prozess noch nicht beendet wurde oder ansonsten eben ein `int` mit dem Returncode. Das sollte doch zur Unterscheidung reichen, oder?

Stefan
BlackJack

Beitragvon BlackJack » Mittwoch 16. April 2008, 12:37

@droptix: Und *jedes* Programm, das sich beendet, gibt einen Returncode zurück, inklusive ``dir`` und ``ls``.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Beitragvon Rebecca » Mittwoch 16. April 2008, 12:42

Jeder Prozess gibt einen Returncode zurueck. Bei shell=True bekommst du den returncode von der Shell.

Mmh, bei mir steht in returncode erst was drin, wenn ich poll aufgerufen habe:

Code: Alles auswählen

>>> p = subprocess.Popen("/bin/ls")
einfuehrung.pdf  einfuehrung.tex
>>> p.returncode
>>> p.returncode
>>> p.returncode
>>> p.returncode
>>> p.returncode
>>> p.poll()
0
>>> p.returncode
0


Code: Alles auswählen

>>> p = subprocess.Popen("echo $HOME", shell=True)
/home/rbreu
>>> p.returncode
>>> p.returncode
>>> p.returncode
>>> p.returncode
>>> p.returncode
>>> p.returncode
>>> p.poll()
0
>>> p.returncode
0


Macht natuerlich sinn, dass man aktiv pollen muss, aber das geht nicht so direktk aus der Doku hervor.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Beitragvon droptix » Mittwoch 16. April 2008, 12:48

Ah genau, das scheint es zu sein. Ohne `poll()` bleibt `returncode` u.U. immer auf `None`. Nun geht's, super! :D
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Beitragvon keppla » Mittwoch 16. April 2008, 13:52

Anstatt poll lieber explizit aufs ende des prozesses (mit .wait()) warten, das scheint das gleiche zu sein.
BlackJack

Beitragvon BlackJack » Mittwoch 16. April 2008, 13:58

@keppla: `wait()` blockiert aber. Die Aufgabenstellung war ja nach x Sekunden nachsehen ob Prozess fertig, wenn nein -> töten.
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Beitragvon droptix » Mittwoch 16. April 2008, 14:31

Genau!

Noch ein Problem: Unter Windows bekomme ich mittels so eine falsche PID zurück:

Code: Alles auswählen

process = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print process.pid


Geprinted wird z.B. 1740, der TaskManager zeigt aber 2112. Wie das?

Unter Linux muss ich das erst noch testen...
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Beitragvon droptix » Mittwoch 16. April 2008, 14:32

Aaaah, es wird die PID der Shell zurück gegeben. So muss man das machen:

Code: Alles auswählen

process = subprocess.Popen(cmd, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print process.pid


[Edit:] Nein, das ist aber auch Mist! So kann ich keine Shell-Befehle wie `dir` mehr ausführen. Da kommt dann sofort dieser Fehler hier:

<type 'exceptions.WindowsError'>:[Error 2] Das System kann die angegebene Datei nicht finden

Also muss ich `shell=True` lassen, dann klappen zumindest alle Befehle... aber ich kann ein GUI-Programm so z.B. nicht nach einem Timeout beenden. Jemand ne Idee dazu?
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Beitragvon keppla » Mittwoch 16. April 2008, 14:56

BlackJack hat geschrieben:@keppla: `wait()` blockiert aber. Die Aufgabenstellung war ja nach x Sekunden nachsehen ob Prozess fertig, wenn nein -> töten.

Uff, sorry, hab das irgendwie auf "was ist der returncode" reduziert. :oops:
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Beitragvon Rebecca » Mittwoch 16. April 2008, 14:58

Anscheinend ist dir (im Gegensatz zu ls unter Linux) kein alleinstehendes Programm, sondern eine Shell-Anweisung.

Warum moechtest du ueberhaupt aus Python heraus Shell-Anweisungen ausfuehren? Immerhin programmierst du ja Python... :wink:
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Beitragvon droptix » Mittwoch 16. April 2008, 15:03

Rebecca hat geschrieben:Warum moechtest du ueberhaupt aus Python heraus Shell-Anweisungen ausfuehren?


Weil es geht... nein ernsthaft: ich bastle eine einfache Python-Shell, um auf einen entfernten Rechner zugreifen zu können.

Idee von mir: alle Prozesse beenden, die als Parent-PID die zurück gegebene PID (also die der Shell) besitzen. Das könnte vielleicht klappen...
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Re: subprocess -> wann beendet?

Beitragvon jens » Mittwoch 16. April 2008, 16:07

droptix hat geschrieben:Ich möchte einen Timeout festlegen, um den Sub-Prozess ggf. automatisch zu beenden, wenn er z.B. nach 15 Sekunden nicht "antwortet".

Ich hab sowas mal gemacht, siehe:
http://www.python-forum.de/post-23692.html#23692
http://www.pylucid.net:8080/pylucid/bro ... ls.py#L477

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
droptix
User
Beiträge: 521
Registriert: Donnerstag 13. Oktober 2005, 21:27

Re: subprocess -> wann beendet?

Beitragvon droptix » Mittwoch 16. April 2008, 16:16

jens hat geschrieben:Ich hab sowas mal gemacht


Danke, aber dient mir leider überhaupt nicht. Ich will ja nicht abwarten, bis der Prozess tatsächlich gekillt wurde und hinterher darauf reagieren. Außerdem ist es komisch zu sagen "Wenn der Prozess 30 Sekunden dauerte und dann mit returncode 0 (= i.d.R. sauberer Exit ohne Fehler) endete, dann wurde er wahrscheinlich gekillt." -> stimmt ja höchst wahrscheinlich nicht und ist total vom Prozess abhängig.

Ich möchte den Prozess gewaltsam beenden, wenn er mir zu lange dauert (oder eben wirklich hängt).
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Mittwoch 16. April 2008, 16:21

Der sourcecode ist schon alt... Der Prozess wird gewaltsam gekillt, nachdem der timeout überschritten wird.

EDIT: Aber:
Da os.kill() nur unter Linux und Mac verfügbar ist, funktioniert das
ganze nicht unter Windows :(

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd

Wer ist online?

Mitglieder in diesem Forum: Majestic-12 [Bot]