@mutetella: Was ist denn für Dich ”der Launcher”? Worauf willst Du überhaupt warten? Nach einem `Popen()` ist das Programm gestartet, da musst Du nicht drauf warten.
Die Prozesse ”senden” auch kein `None`. Was Du mit `poll()` abfragst ist der Rückgabecode des Prozesses. Und solange der noch läuft bekommst Du halt `None` von diesem Aufruf zurück weil es noch keinen Rückgabecode gibt, denn der steht ja erst am Ende des Prozesses fest. Wenn Du von `poll()` etwas anderes als `None` zurück bekommst dann gibt es den Prozess nicht mehr. Es macht also auch keinen Sinn danach noch weiter `poll()` aufzurufen, weil das natürlich immer den selben Wert liefert, eben den Rückgabecode den der Prozess am Ende per `exit()` an das Betriebssystem zurückgegeben hat.
Mit subprocess.call xterm starten und parent schließen
@mutetella:
Die exec*-Calls geben Dir überhaupt nie was zurück, wie auch - exec ersetzt den aktuellen Prozess mit dem neuen, d.h. alles was nach exec* in Deinem Skript kommt, wird nie erreicht.
Warum muss die Auswahl eigentlich in einem neuem Terminal laufen und das alte geschlossen werden? Warum nicht einfach im selben Terminal bleiben? Da kannst Du prima mit exec Prozesshopping betreiben.
Wie stellst Du überhaupt sicher, dass das Terminal mit Skriptende auch mit geschlossen wird? Zwar verhalten sich die meisten Emulatoren unter X so, das OSX Terminal z.B. aber nicht - dort bleibt das Terminalfenster mit einer letzten Statusmeldung offen. Um hier sicher zu gehen, müsstest Du das Terminal selbst abschiessen.
@BlackJack:
In mutetellas Ansinnen müsste man tatsächlich mindestens solange warten, bis der Subprozess sich detached hat, um nicht als noch Kindprozess mit dem Terminal mit beendet zu werden.
Die exec*-Calls geben Dir überhaupt nie was zurück, wie auch - exec ersetzt den aktuellen Prozess mit dem neuen, d.h. alles was nach exec* in Deinem Skript kommt, wird nie erreicht.
Warum muss die Auswahl eigentlich in einem neuem Terminal laufen und das alte geschlossen werden? Warum nicht einfach im selben Terminal bleiben? Da kannst Du prima mit exec Prozesshopping betreiben.
Wie stellst Du überhaupt sicher, dass das Terminal mit Skriptende auch mit geschlossen wird? Zwar verhalten sich die meisten Emulatoren unter X so, das OSX Terminal z.B. aber nicht - dort bleibt das Terminalfenster mit einer letzten Statusmeldung offen. Um hier sicher zu gehen, müsstest Du das Terminal selbst abschiessen.
@BlackJack:
In mutetellas Ansinnen müsste man tatsächlich mindestens solange warten, bis der Subprozess sich detached hat, um nicht als noch Kindprozess mit dem Terminal mit beendet zu werden.
@mutetella: so langsam verstehe ich, was Du zu erreichen versuchst.
Du startest Deinen Launcher über `xterm -e launcher`. Dann willst Du eine Auswahl treffen, ein neues Programm soll gestartet werden und das alte xterm-Fenster geschlossen werden. Dazu mußt Du wissen, dass alle Kinder und Kindeskinder eines Prozesses das Signal SIGHUP gesendet bekommen, wenn ein xterm-Fenster geschlossen wird. Das beendet normalerweise den Prozess, außer man ignoriert das Signal.
Du startest Deinen Launcher über `xterm -e launcher`. Dann willst Du eine Auswahl treffen, ein neues Programm soll gestartet werden und das alte xterm-Fenster geschlossen werden. Dazu mußt Du wissen, dass alle Kinder und Kindeskinder eines Prozesses das Signal SIGHUP gesendet bekommen, wenn ein xterm-Fenster geschlossen wird. Das beendet normalerweise den Prozess, außer man ignoriert das Signal.
Code: Alles auswählen
import os
import signal
items = [
('ranger', ('xterm', '-e', 'ranger')),
('iceweasel', ('iceweasel',))
]
def start():
for idx, item in enumerate(items):
print '{:2d} {}'.format(idx, item[0])
choice = int(raw_input('> '))
app = items[choice][1]
signal.signal(signal.SIGHUP, signal.SIG_IGN)
pid = os.fork()
if pid == 0:
os.execvp(app[0], app)
if __name__ == '__main__':
start()
Das ist mir schon klar. Nur ist es halt so, dass der Kindprozess erst gar nicht zum Starten kommt, wenn der Elternprozess zu früh beendet wird. Wenn ich also ohne zeitliche Verzögerung ``p = subprocess.Popen(wasauchimmer); sys.exit()`` mache, dann startet `wasauchimmer` erst gar nicht, weil der Elternprozess zuvor schon wieder geschlossen wird. Ich dachte eben, dass es evtl. eine Möglichkeit gibt, `p` abzufragen, ob das zugrundeliegende Programm bereits gestartet ist.BlackJack hat geschrieben:Die Prozesse ”senden” auch kein `None`. Was Du mit `poll()` abfragst ist der Rückgabecode des Prozesses.
Ich verwende i3 als Fenstermanager. Das Launcherskript möchte ich in einem floating window starten, die daraus gestarteten Programme aber nicht.jerch hat geschrieben:Warum muss die Auswahl eigentlich in einem neuem Terminal laufen und das alte geschlossen werden?
Den Job übernimmt X für mich. Und OSX interessiert mich nicht...jerch hat geschrieben:Wie stellst Du überhaupt sicher, dass das Terminal mit Skriptende auch mit geschlossen wird?
@Sirius3
Sind meine Kommentare richtig?
Code: Alles auswählen
# if SIGHUP occurs, ignore it
signal.signal(signal.SIGHUP, signal.SIG_IGN)
# create new child process
pid = os.fork()
# start app within child if creation not fails
if pid == 0:
os.execvp(app[0], app)
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit )
@mutetella: Der ' if creation not fails'-Zusatz ist falsch. Ob die Erzeugung geklappt hat wird da nicht geprüft, sondern in welchem der beiden Prozesse man sich befindet.
Um der Sache auf die Schliche zu kommen, hier mal eine quick&dirty Funktion dazu:Ruft man diese mit `print_processpath(os.getpid())` auf, so sieht man die Elternprozesse (PID und Command) bis zum Root-Prozess (init). Das Flag dahinter zeigt an, ob ein Prozess session leader ist. Was es alles damit auf sich hat - siehe http://ftp.gnu.org/old-gnu/Manuals/glib ... bc_27.html
Ruft man das in einem xterm mit Shell in ipython auf, sieht es so aus: in 'xterm ipython' dagegen:
xterm verhält sich nun so, dass es sich beendet, wenn der erste session leader am pty-slave stirbt (dabei wird das SIGHUP an alle Kinder ausgelöst). Alternativ könnte man auch xterm direkt beenden, was der Urbedeutung des SIGHUP (Gegenstelle des Terminals hat aufgelegt) gleich kommt und immer dann passiert, wenn man den Schliessen-Button des Fenstermanagers drückt.
Code: Alles auswählen
def print_processpath(pid):
while pid:
print os.popen('ps -p %d -opid=,command=' % pid).read().strip(), os.getsid(pid) == pid
pid = int(os.popen('ps -p %d -oppid=' % pid).read().strip())
Ruft man das in einem xterm mit Shell in ipython auf, sieht es so aus:
Code: Alles auswählen
In [5]: print_processpath(os.getpid())
13689 /usr/bin/python /usr/bin/ipython False
13441 bash True
13439 /usr/bin/xterm False
4187 init --user True
4161 lightdm --session-child 12 25 False
1188 lightdm True
1 /sbin/init True
Code: Alles auswählen
In [3]: print_processpath(os.getpid())
13769 /usr/bin/python /usr/bin/ipython True
13767 xterm ipython False
13441 bash True
13439 /usr/bin/xterm False
4187 init --user True
4161 lightdm --session-child 12 25 False
1188 lightdm True
1 /sbin/init True