ubuntuusers.de

Python: Anderes Programm öffnen

Status: Gelöst | Ubuntu-Version: Ubuntu 11.10 (Oneiric Ocelot)
Antworten |

Developer92 Team-Icon

Avatar von 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:

1
2
3
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 Team-Icon

Moderator & Supporter
Avatar von redknight

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 Team-Icon

(Themenstarter)
Avatar von Developer92

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 Team-Icon

(Themenstarter)
Avatar von Developer92

Anmeldungsdatum:
31. Dezember 2008

Beiträge: 4101

Ganz so einfach ist es jetzt doch nicht.

Ich gebe im Terminal das hier ein:

1
nohup xdg-open video

Wenn ich jetzt den Terminal beende läuft das Video weiter.

Und jetzt ein wenig Python:

1
2
3
4
5
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 Team-Icon

(Themenstarter)
Avatar von Developer92

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:

1
2
3
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

Avatar von 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:

1
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

Avatar von 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

Avatar von 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.

Antworten |