Developer92
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
Hallo, folgendes Problem: Ich will mit Python bestimmte Dateien öffnen lassen via xdg-open. Das Problem dabei: Wenn sich das Skript beendet, wird auch die Anwendung, welche von xdg-open geöffnet wurde, geschlossen. Folgendes habe ich schon probiert: | os.system('xdg-open file')
os.system('xdg-open file &')
subprocess.Popen(['xdg-open', 'file'])
|
Bei allen 3 Versuchen hat sich auch das von xdg-open geöffnete Programm geschlossen, wenn sich das Skript beendet hat. Gibt es eine Möglichkeit, das zu umgehen? mfg
|
DiBo33
Anmeldungsdatum: 16. Juni 2006
Beiträge: 1827
|
mit nohup xdg-open file starten
|
redknight
Moderator & Supporter
Anmeldungsdatum: 30. Oktober 2008
Beiträge: 21850
Wohnort: Lorchhausen im schönen Rheingau
|
Im Falle der ZSH musst du einem solchen Fall explizitin disown nutzenb, also nicht xdg-open file & sondern xdg-open file &! Eventuell ist das bei dir auch der Fall.
|
Developer92
(Themenstarter)
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
redknight schrieb: Im Falle der ZSH musst du einem solchen Fall explizitin disown nutzen
Nö, hier wird momentan die bash verwendet ☺ Allerdings sollte ich das im Hinterkopf behalten, nicht dass doch mal die zsh verwendung findet. Mit 'nohup' funktioniert es im übrigen, Danke. mfg
|
Developer92
(Themenstarter)
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
Ganz so einfach ist es jetzt doch nicht. Ich gebe im Terminal das hier ein:
Wenn ich jetzt den Terminal beende läuft das Video weiter. Und jetzt ein wenig Python:
| subprocess.Popen(['nohup', 'xdg-open', 'video']) # Video läuft, schließt sich aber bei Beenden des Python-Programms
subprocess.Popen(['nohup', 'xdg-open', 'video', '&']) # Video erscheint erst gar nicht
subprocess.Popen(['nohup', 'xdg-open', 'video', '&!']) # Video erscheint auch nicht
subprocess.Popen(['nohup', 'totem', 'video1', 'video2']) # Video läuft und bleibt auch nach schließen des Python-Programms offen
subprocess.Popen(['nohup', 'totem', 'video1']) # Hier der gleiche Fall
|
Sieht irgendwie nach nem Fehler in "xdg-open" aus. Ich hab auch Totem durch andere Programme wie VLC ersetzt und auch da funktioniert es. Nur bei xdg-open kann ich das Skript nicht beenden, ohne dass der Videoplayer auch beendet wird. mfg
|
Kinch
Anmeldungsdatum: 6. Oktober 2007
Beiträge: 1261
|
Öffnet subprocess.Popen überhaupt ne Shell? Wenn nicht, dann funktionieren selbstverständlich auch keine Shell-Befehle, wie &. Der korrekte Weg wäre übrigens SIGHUP abzufangen. Du müsstest dazu schauen, wie man in Python mit Signalen umgeht.
|
Developer92
(Themenstarter)
Anmeldungsdatum: 31. Dezember 2008
Beiträge: 4101
|
Kinch schrieb: Öffnet subprocess.Popen überhaupt ne Shell? Wenn nicht, dann funktionieren selbstverständlich auch keine Shell-Befehle, wie &.
Hm, da hast du Recht. Ich kann allerdings den Parameter "shell=True" dranhängen. Allerdings meckert dann nohup: | subprocess.Popen(['nohup', 'xdg-open', 'video1'], shell=True)
nohup: fehlender Operand
„nohup --help“ gibt weitere Informationen.
|
Geht also auch nicht wirklich. Anscheinend wird xdg-open nicht an nohup drangehängt. Und beendet sich somit...
Der korrekte Weg wäre übrigens SIGHUP abzufangen. Du müsstest dazu schauen, wie man in Python mit Signalen umgeht.
Du meinst, dass SIGHUP nicht an xdg-open bzw. nohup weitergeleitet wird? Oder wie muss ich das verstehen? mfg
|
Kinch
Anmeldungsdatum: 6. Oktober 2007
Beiträge: 1261
|
Developer92 schrieb: Du meinst, dass SIGHUP nicht an xdg-open bzw. nohup weitergeleitet wird? Oder wie muss ich das verstehen?
Wenn der Vater-Prozess geschlossen wird, wird ein Sighup an das Kind gesendet und das Kind beendet sich dann meistens. Um das zu umgehen muss Sighup beim Kind abgefangen werden. Das ist auch genau das, was nohup tut. Es startet einen neuen Prozess, den nohup-Prozess und startet dann das eigentlich Kommando als Kind-Prozess, bei dem Sighup abgefangen wird. Es würde reichen, dass auch in Python so zu machen. Wie genau du Signale abfängst musst du in der Doku nachlesen. Dann brauchst du natürlich auch 'nohup' gar nicht mehr.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17621
Wohnort: Berlin
|
Wenn ich - als Nicht-Pythonier - meine Javakenntnisse auf die Fragestellung anwenden darf, dann würde ich sagen: | subprocess.Popen(['/bin/sh', '-c', 'nohup xdg-open video &'])
|
|
Kinch
Anmeldungsdatum: 6. Oktober 2007
Beiträge: 1261
|
Klar, würde das funktionieren. Die Sache ist nur: Will man so eine Lösung? Ziel ist es einen Sub-Prozess zu starten, der sich nicht selbst beendet. Um das zu erreichen, wird dann ein neuer Sub-Prozess gestartet, damit dieser einen Sub-prozess starten kann, der dann den eigentlichen Sub-Prozess als Sub-Prozess startet. Es macht zugegeben keinen praktischen Unterschied, aber die Lösung finde ich etwas unelegant. Darüberhinaus holt man sich natürlich auch gewisse Abhängigkeiten mit ins Boot. Ich glaube zwar nicht, dass das Programm mal unter Windows laufen würde, aber reine Python-Lösung könnte zumindest auch unter nicht Unixen laufen. Die Frage ist auch, ob Python für so ein Skript überhaupt die richtige Wahl ist. Gerade das Verwalten von Subprozessen geht unter Shells (insbesondere der Phantastischen Z-Shell) ja sehr einfach und schnell. Ich habe schon wirklich einige Python-Skripte gesehen, die so aufgebaut sind: os.system("mkdir …")
os.system("ls …")
os.system("mv …") Und ich versteh es nicht, wieso man sowas macht. Macht den os.system-Quatsch weg, tauscht die Shebang und das Teil läuft auch so.
|
Vain
Anmeldungsdatum: 12. April 2008
Beiträge: 2510
|
Kinch schrieb: Wenn der Vater-Prozess geschlossen wird, wird ein Sighup an das Kind gesendet und das Kind beendet sich dann meistens.
Du sagst das mit so einer Überzeugung, dass mich das völlig verunsichert. Bist du sicher? Soweit ich weiß, sendet nur ein Terminal bei seinem Beenden ein SIGHUP an seinen Prozess, was meistens eine Shell ist, die dann wiederum aktiv SIGHUPs an ihre Prozesse verteilt, sofern die nicht mit „disown “ aus der Liste ausgetragen wurden. Aber eigentlich™ wird doch ein Prozess, wenn sein Elternprozess stirbt, einfach an init übergeben, oder? Hat eigentlich mal jemand versucht, das Problem nachzustellen? Ich schaffe das nicht. Einzig dann, wenn ich das Python-Skript mit ^C abwürge, stirbt auch das Kind, was aber ein Nebeneffekt von ^C sein dürfte und nicht am SIGINT liegt. Denn schicke ich gezielt ein SIGINT an den Python-Prozess, bleibt das Kind am Leben. Wie so oft, ich bin verwundert. Nichts mit dem Problem sollte zu tun haben, dass da immer Zombies entstehen, wenn das Kind mal vor Python zuende ist. Ich würde da ein „signal.signal(signal.SIGCHLD, signal.SIG_IGN) “ vor dem „Popen(...) “ absetzen, aber ein Python-Liebhaber möge mich da korrigieren, wenn’s schöner geht.
|
DiBo33
Anmeldungsdatum: 16. Juni 2006
Beiträge: 1827
|
Hat eigentlich mal jemand versucht, das Problem nachzustellen?
Ja ich, aber ebenso wenig wie du schaffe ich es auch nicht das Szenario so herzustellen das der Prozess beendet wird.
|
Barabbas
Anmeldungsdatum: 31. März 2007
Beiträge: 1651
Wohnort: Münster
|
Hallo, bei Verwendung von "shell=true" erwartet Popen keine Liste von Befehlen und Parametern, sondern den Befehl als String. import subprocess
subprocess.Popen("nohup totem", shell=True) Das funktioniert wie erwartet - das Programm schließt sich nicht. Ob und in wie weit Python hier geeignet ist, hängt natürlich von der konkreten Anwendung ab, aus einem einzigen Aufruf kann man schlecht schließen, ob/dass es sich nicht vielleicht doch um »os.system("mkdir...")« Programmierung handelt. Grundsätzlich ist "nohup" natürlich auch ein externes Programm, für das man bspw. unter Windows eine Alternative benötigt (denke ich mal). Die "hauseigene" Variante wäre vermutlich, den Process mit der Doppelfork-Technik vom Terminal zu lösen. Ob und in wie weit das plattformunabhänging und verlässlich ist, kann ich gerade nicht sagen - aber das schiene mir erstmal eine mögliche Alternative zu sein. lG brb
|
DiBo33
Anmeldungsdatum: 16. Juni 2006
Beiträge: 1827
|
Grundsätzlich ist "nohup" natürlich auch ein externes Programm, für das man bspw. unter Windows eine Alternative benötigt (denke ich mal).
Ja, die Alternative unter Windows heisst start.exe
|
Kinch
Anmeldungsdatum: 6. Oktober 2007
Beiträge: 1261
|
Vain schrieb: Du sagst das mit so einer Überzeugung, dass mich das völlig verunsichert. Bist du sicher? Soweit ich weiß, sendet nur ein Terminal bei seinem Beenden ein SIGHUP an seinen Prozess, was meistens eine Shell ist, die dann wiederum aktiv SIGHUPs an ihre Prozesse verteilt, sofern die nicht mit „disown “ aus der Liste ausgetragen wurden. Aber eigentlich™ wird doch ein Prozess, wenn sein Elternprozess stirbt, einfach an init übergeben, oder?
Ja, tut mir leid für die Verunsicherung. Meine Darstellung war vereinfacht. Sighups kommen historisch gesehen von den Terminals (den physischen) und ich glaube, auch nur die Nutzen das in der Art. Ich dachte aber zugegeben auch, das Problem entstünde beim schließen des Terminals.
|