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.
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 16. April 2008, 17:37

Hab das ganze nochmal überarbeitet...
http://trac.pylucid.net/browser/trunk/p ... y?rev=1634

Dabei ist zu beachten, das man stdout und stderr nur dann lesen kann, wenn der Prozess normal beendet wurde. Wurde der Process abgeschossen, blockiert das .read()...

Eine Idee wie man das umgehen kann???

EDIT: Link aktualisiert.
Zuletzt geändert von jens am Freitag 31. Oktober 2008, 15:20, insgesamt 1-mal geändert.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 16. April 2008, 19:27

lunar hat geschrieben:SIGTERM nutzen.
Warum, kannst du das näher erläutern? Ich kenne mich da nicht so richtig aus...

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

Mittwoch 16. April 2008, 19:57

jens hat geschrieben:Wurde der Process abgeschossen, blockiert das .read()...
Das Problem habe ich auch. Ich umgehe das einfach damit, dass ich .read() erst durchführe, wenn .returncode nicht gleich None ist (andernfalls greift sowieso der Timeout und killt den Prozess). Ich weiß aber nicht, wie viel Output dabei gepuffert wird.

Ich mache übrigens noch eine kleine Unterscheidung in Windows und Unix/Mac:

Code: Alles auswählen

TIMEOUT = 3
PLATFORM = sys.platform

if PLATFORM == "win32":
	import win32api
	import win32con
	import win32process
else:
	import os
	import signal

# ... somewhere else:

			process = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
			t = time.time()
			while True:
				process.poll()
				if process.returncode is not None:
					output = process.stdout.read()
					returnCode = process.returncode
					break
				elif time.time() - t >= TIMEOUT:
					# try to kill process
					try:
						if PLATFORM == "win32":
							try:
								h = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, process.pid)
								handle = h.handle
								win32process.TerminateProcess(handle, 1)
								killed = process.pid
							except Exception, e:
								killed = e
						else:
							try:
								os.kill(process.pid, signal.SIGUSR1)
								killed = process.pid
							except Exception, e:
								killed = e
					finally:
						break
				time.sleep(0.5)
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Mittwoch 16. April 2008, 21:15

jens hat geschrieben:
lunar hat geschrieben:SIGTERM nutzen.
Warum, kannst du das näher erläutern? Ich kenne mich da nicht so richtig aus...
Es gibt ja viele verschiedene Signale. SIGTERM (15) ist quasi die freundliche Bitte an den Prozess, sich ordnungsgemaess zu beenden. Der Prozess kann dann noch aufraeumen, koennte das Signal sogar ignorieren. IMO wird z.B. ein SIGTERM gesendet, wenn du im Fenster-Titel auf das "x" clickst.

SIGKILL (9) hingegen ist ein hartes, sofortiges Abschiessen des Prozesses und sollte nur verwendet werden, wenn SIGTERM nicht mehr hilft.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 17. April 2008, 06:03

Rebecca hat geschrieben:SIGKILL (9) hingegen ist ein hartes, sofortiges Abschiessen des Prozesses und sollte nur verwendet werden, wenn SIGTERM nicht mehr hilft.
So etwas hatte ich mir schon gedacht, aber ich wußte nicht welches signal die passendsten sind.

Also dann könnte man es so machen, wie du vorgeschlagen hast. Nach dem timeout erstmal nur SIGTERM senden, dann nochmal einen timeout abwarten und nochmal SIGKILL hinterher schicken...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Donnerstag 17. April 2008, 09:40

jens hat geschrieben:Also dann könnte man es so machen, wie du vorgeschlagen hast. Nach dem timeout erstmal nur SIGTERM senden, dann nochmal einen timeout abwarten und nochmal SIGKILL hinterher schicken...
So macht Linux das beim runterfahren auch. :wink:
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 23. April 2008, 12:12

droptix hat geschrieben:Ich mache übrigens noch eine kleine Unterscheidung in Windows und Unix/Mac:
Ich hab meine Variante auf Basis von deinem umgestrickt. Nun auch ohne Threading und mit dem senden von zwei Signalen:
https://github.com/jedie/PyLucid/blob/a ... rocess2.py

EDIT (jens): Link aktualisiert.
EDIT2: wieder aktualisiert ;)

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