externe Programmaufrufe, Fenster blockiert + Fehler abfangen

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Benutzeravatar
lbuega
User
Beiträge: 75
Registriert: Dienstag 15. April 2003, 08:51
Wohnort: Weissach

externe Programmaufrufe, Fenster blockiert + Fehler abfangen

Beitragvon lbuega » Montag 30. Juni 2003, 09:41

Hallo,
ich möchte von meinem Programm aus (mit GUI) externe Programme aufrufen. Doch hier fangen meine Probleme an:

Code: Alles auswählen

def programmaufruf(startbefehl):
    """
    Funktion für Programmaufrufe.
    Führt den als String übergebenen 'startbefehl' aus.
    """
    try:
        os.system(startbefehl)
    except:
        #...öffnen eines Fensters mit der Fehlermeldung...

1. "startbefehl" korrekt:
Das aufgerufene Programm läuft, aber meine GUI ist nicht mehr ansprechbar! Erst nach schließen des aufgerufenen Programms ist dies wieder möglich. Meine GUI (Programm) soll aber die ganze Zeit ansprechbar sein!?!

2. "startbefehl" unbekannt/fehlerhaft:
die Fehlermeldung wird in meinem Eingabefenster (UNIX: xterm, vergleichbar mit DOS-Box) ausgegeben. Wie kann ich diese abfangen um sie von meiner GUI dem User in einem extra Fenster zu präsentieren?
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Re: externe Programmaufrufe, Fenster blockiert + Fehler abfa

Beitragvon Voges » Montag 30. Juni 2003, 11:09

Hallo!

zu 1.
Abhängig davon, was Du genau erreichen willst und welche GUI-Lib Du nutzt, käme vielleicht ein eigener Thread infrage.

zu 2.
Anstelle system() könntest Du z.B. popen3() nehmen. Die Funktion gibt ein Tupel zurück, bei dem das 3. Element ein "file-like" Objekt ist, das die Fehlermeldung enthält. (Such mal im Forum nach open2(), -3() oder -4(). War schon häufig Thema.)

Das Ganze könnte so aussehen (ungetestet):

Code: Alles auswählen

import thread
def startThread(startbefehl):
    errorMsg = os.popen3(startbefehl)[2].readlines()
    if errorMsg:
        #...öffnen eines Fensters mit der Fehlermeldung...

def programmaufruf(startbefehl):
    """
    Funktion für Programmaufrufe.
    Führt den als String übergebenen 'startbefehl' aus.
    """
    thread.start_new_thread(startThread,(startbefehl,))

Jan
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Montag 30. Juni 2003, 12:58

Hi,

alternativ gibts im os-Modul auch die spawn-Funktionen um externe Programme zu starten. Mit dem Parameter P_NOWAIT, als ersten Parameter, werden die Programme als separate Threads gestartet.
Siehe http://www.python.org/doc/current/lib/os-process.html


Gruß

Dookie
Benutzeravatar
lbuega
User
Beiträge: 75
Registriert: Dienstag 15. April 2003, 08:51
Wohnort: Weissach

Beitragvon lbuega » Dienstag 1. Juli 2003, 09:37

Das mit "popen3"ist eine feine Sache, liefert mir problemlos das entsprechende Ergebnis des beendeten ausgeführten Programms. Aber leider ist beim Aufruf meine GUI trotzdem noch blockiert. In der Python Library Reference (http://www.python.org/doc/current/lib/os-process.html) steht, dass ein "child"-Prozess erzeugt wird. Heisst das, dass dann das der "parent"-Prozess automatisch blockiert ist?

Code: Alles auswählen

def programmaufruf(startbefehl):
    ch_out,ch_in,ch_err = popen2.popen3(startbefehl)

#    befehl=raw_input("weiteren Befehl eingeben: ")
#    ch_in.write(befehl)
#    ch_in.close()
 
    #Überprüfen, welche Art der Rückgabe des ausgeführten Programms besteht,
    #(O.k. oder Fehler) und diese entsprechend zurückgeben
    line_out = ch_out.readlines()
    line_err = ch_err.readlines()
    if ( line_err == []):
        return line_out
    else:
        return line_err
...und warum funktioniert das "ch_in.write()" nicht?

Mit den spawn*-Befehlen komme ich leider nicht klar, habe mal nach einer dt. Info gegoogelt - leider negativ und im Forum wird auch nur aufs englische Original verwiesen, ohne weitere Erklärung. Wober diese ja wohl als extra/neuer Prozess gestartet werden würden. Aber bekommt man da auch ein OK/Fehler-"Return" vom ausgeführten Prog? (für was stehen die ... Punkte? Warum ist das nicht wie sonst mit [] bei optionalen Elementen? Was ist die env-Variable?)
Bei ausführen von nachstehendem passiert sichtbar garnichts (zb. wenn man es für "startbefehl" mit einem "ls" oder "xterm" aufruft etc.):

Code: Alles auswählen

os.spawnl(os.P_NOWAIT, startbefehl)


Vielleicht kurz zur Erklärung warum ich das benötige: Eine Python-Prog mit Tkinter-GUI soll später auf Win und Unix laufen und dort Programme aufrufen, Datei und Stringoperationen ausführen etc. Natürlich soll mein Prog dann nicht die ganze Zeit blockiert sein während ein aufgerufenes Programm läuft sondern weiterhin ansprechbar sein. Ausserdem soll es Fehlermeldungen von einem der aufgerufenen Programme (sei es wg. eines fehlerhaften Befehls etc.) entgegennehmen und verarbeiten können.
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Beitragvon Voges » Dienstag 1. Juli 2003, 10:56

Hallo!
lbuega hat geschrieben:Aber leider ist beim Aufruf meine GUI trotzdem noch blockiert.
Startest Du denn die Funktion, wie vorgeschlagen, in einem eigenen Thread?

lbuega hat geschrieben:Mit den spawn*-Befehlen komme ich leider nicht klar, habe mal nach einer dt. Info gegoogelt - leider negativ und im Forum wird auch nur aufs englische Original verwiesen, ohne weitere Erklärung.
Es gibt wenige Funktionen, die in der Doku so gut beschrieben sind, wie spawn*, sogar mit 2 Beispielen. Sorry, aber für das Verstehen von the env parameter ... is used to define the environment variables for the new process sollte Mittelstufenenglisch eigentlich reichen, zumal wenn es aus dem Code-Beispiel herleitbar ist.

Die drei Punkte in der Doku stehen für eine beliebige Zahl von Argumenten größer 0, also quasi für unendlich verschachtelte eckige Klammern arg[,arg[,arg[,arg[,arg[<usw>]]]]].

lbuega hat geschrieben:Bei ausführen von nachstehendem passiert sichtbar garnichts (zb. wenn man es für "startbefehl" mit einem "ls" oder "xterm" aufruft etc.):
Natürlich nicht. spawnl() erwartet den kompletten Pfad zum Programm (siehe Doku). Zudem muss das 1. Argument der Argumentenliste (die drei Punkte) nochmal der Befehl selbst sein (siehe Doku, insbesondere die Beispiele).
Jan
Benutzeravatar
lbuega
User
Beiträge: 75
Registriert: Dienstag 15. April 2003, 08:51
Wohnort: Weissach

Beitragvon lbuega » Dienstag 1. Juli 2003, 13:47

Voges hat geschrieben:Hallo!
Startest Du denn die Funktion, wie vorgeschlagen, in einem eigenen Thread?
Noch nicht, habs erstmal so probiert. Dachte es funzt auch ohne.

Voges hat geschrieben:Es gibt wenige Funktionen, die in der Doku so gut beschrieben sind, wie spawn* ...englisch eigentlich reichen...
:shock: Bitte!?!
Um's Englisch gehts beim besten willen nicht :roll:, das ist mehr ne computertechnische Frage... Was für Umgebungs-Parameter? Was bewirken diese?

Voges hat geschrieben:Die drei Punkte in der Doku stehen für eine beliebige Zahl von Argumenten größer 0, also quasi für unendlich verschachtelte eckige Klammern arg[,arg[,arg[,arg[,arg[<usw>]]]]].
Interessant... und was werden da für Argumente erwartet? wie werden die verarbeitet?

Voges hat geschrieben:Natürlich nicht. spawnl() erwartet den kompletten Pfad zum Programm (siehe Doku).
Ok, das geb ich zu hab ich grosszügig überlesen, da bei dem Beispiel auch direkt der "cp"-Befehl (falls das auch tatsächlich dieser ist?) genommen wurde; aber ist ja eine andere spawn-Order

Voges hat geschrieben:Zudem muss das 1. Argument der Argumentenliste (die drei Punkte) nochmal der Befehl selbst sein (siehe Doku, insbesondere die Beispiele). Jan
:x Super! Bei "spawnl(mode, path, ...)" steht davon überhaupt nichts! Dies würde ich eher so interpretieren, dass nur mode und path benötigt werden. Woher soll man da was anderes vermuten??? Dann sind die "..." (drei Punkte) also auch keine opionalen Argumente sondern müssen wohl angeben werden!?! Daraus soll einer schlau werden?!?
Ich versuche ja noch irgendwie die spawn-Befehle zu durchschauen... :cry: Schon allein wenn ich verstehen könnte was das Beispiel aus der Py.Lib.Ref. macht wäres für mich etwas leichter nachzuvollziehen:

Code: Alles auswählen

os.spawnlp(os.P_WAIT, 'cp', 'cp', 'index.html', '/dev/null')

Vielen Dank für Deine Unterstützung. (und nimms nicht persönlich falls der Ton etwas agressiv sein sollte, reg mich grad bloß auf weil mich das so lange aufhält und ich nicht durchsteig...)
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Dienstag 1. Juli 2003, 14:10

Hi,

bei mir steht in der Doku zu spawn zu lesen
In either case, the arguments to the child process must start with the name of the command being run

Übersetzung:
In jedem Falle, die Argumente für den Kindprozess müssen mit dem Namen des zu startenden Komandos beginnen.


Gruß

Dookie
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Beitragvon Voges » Dienstag 1. Juli 2003, 15:38

Hallo!
Was für Umgebungs-Parameter? Was bewirken diese?
Mach mal set | more in Deiner Shell (geht auch unter Windows). Das, was dann hoffentlich erscheint, sind Umgebungsvariablen. Die Informationen, die diese Variablen enthalten, stehen allen Prozessen zur Verfügung, die aus der Shell gestartet werden. Bei den spawn*e-Funktionen hast Du nun die Möglichkeit, solche Variablen dem zu startenden Prozess bekannt zu machen eben über den Parameter env.

Interessant... und was werden da für Argumente erwartet? wie werden die verarbeitet?
Das sind die Aufrufparameter (command-line arguments), mit der Du das Programm starten willst, also bei ls z.B. -alF.

Dann sind die "..." (drei Punkte) also auch keine opionalen Argumente sondern müssen wohl angeben werden!?!
"größer 0" schrieb ich. Aber steht ja auch nochmal im Text. Dookie hat die Stelle ja genannt.

Ich stell' nochmal Beispiel und Doku gegenüber, damit die Zuordnung vielleicht klarer wird:

Code: Alles auswählen

os.spawnlp(  os.P_WAIT,   'cp',    'cp', 'index.html', '/dev/null')
#  spawnlp(  mode,        file,    ...                            )
   
os.spawnvpe( os.P_WAIT,   'cp',    ['cp', 'index.html', '/dev/null'],   os.environ)
#  spawnvpe( mode,        file,    args,                                env       )


Diese Prozessgeschichten sind alles andere als trivial, zumal wenn Du auch noch die Prozesse zur Laufzeit steuern willst.
Jan

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder