Verhalten nach Aufruf von 'os.execv()'

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.
tobias.vdk
User
Beiträge: 19
Registriert: Mittwoch 23. November 2005, 16:51

Verhalten nach Aufruf von 'os.execv()'

Beitragvon tobias.vdk » Montag 3. Juli 2006, 10:03

Hallo!

Nach dem Aufruf von

Code: Alles auswählen

os.execv()
werden bei mir alle Befehle ignoriert.

Code: Alles auswählen

$ python -V
Python 2.4.3


Ein Beispiel:

Code: Alles auswählen

#!/usr/bin/env python

import os

print 'test'
ConfigFileName = '/home/l142051/testfile'
os.execv('/bin/touch', ['touch', ConfigFileName])
print 'test'

bringt nur einmal :!: 'test' in der Shell.

Weiß jemand, woran das liegen könnte?

Tschau Tobias
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Beitragvon Rebecca » Montag 3. Juli 2006, 10:20

Zu den exec*-Funktionen:
Python Doku hat geschrieben:These functions all execute a new program, replacing the current process; they do not return.

D.h. der touch-Prozess ersetzt den alten Prozess, wird ausgefuehrt, und wenn touch fertig ist, beendet es sich und damit dein ganzes Programm. Sieht man sehr schoen hier:

Code: Alles auswählen

>>> import os
>>> ConfigFileName = '/home/rbreu/bla'
>>> os.execv('/bin/touch', ['touch', ConfigFileName])
rbreu@abby:~>
Der Python-Interpreter wird einfach beendet.

Du muesstest zuerst einen Kindprozess starten, in dem dein touch ausgefuehrt wird:

Code: Alles auswählen

pid = fork();
if pid == 0:
    #Kindprozess:
    os.execv(...)
else:
    #Eltern-Prozess: soll auf Kindprozess warten:
    os.waitpid(pid);
    print "Fertig."

Das ist aber sehr lowlevel. Wahrscheinlichs bist du mit dem Modul subprocess oder den popen-Sachen besser bedient.
Zuletzt geändert von Rebecca am Montag 3. Juli 2006, 11:28, insgesamt 1-mal geändert.
tobias.vdk
User
Beiträge: 19
Registriert: Mittwoch 23. November 2005, 16:51

Beitragvon tobias.vdk » Montag 3. Juli 2006, 10:39

Ich habe jetzt den Befehl ersetzt durch

Code: Alles auswählen

os.system('/usr/bin/touch /home/l142051/testfile')


Was ist denn der Unterschied zwischen den beiden Varianten?
Ist eine zu bevorzugen?

Tschau Tobias
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Beitragvon Rebecca » Montag 3. Juli 2006, 11:48

(Wieder mal: Folgendes gilt fuer Linux/Unix, von Win und Dos habe ich keinen Plan...)
Wenn ein Prozess einen anderen Prozess starten moechte, gibt's dazu die Linux-System-Calls exec*. In der Python-Doku steht das zwar nicht, aber ich schaetze, die gleichnamigen Python-Funktionen rufen im Wesentlichen einfach diese System-Calls auf, jedenfalls funktionieren die System-Calls auch so wie ich oben beschrieben habe: Der neue Prozess wird in den Speicher geladen, dabei wird der alte Prozess vollkommen ersetzt, dann wird der neue Prozess ausgefuehrt. Ist der neue Prozess zuende, gibt's keine Moeglichkeit, zu dem alten Prozess zurueckzukehren, da der nicht mehr im Speicher ist. Dies ist die einzige Moeglichkeit fuer einen Unix-Prozess, einen neuen Prozess zu starten.

Moechte man einen "Subprozess" ausfuehren, sodass das alte Programm waehrend oder nach Ausfuehren des neuen Prozesses weiterlaeuft, muss man den fork-System-Call benutzen (dazu gibt's ja auch die entsprechende Python-Funktion). Der erzeugt einen Kindprozess, der zunaechst genau das gleiche Programm ausfuehrt wie der urspruengliche Prozess. Den Kindprozess laesst man dann exec* mit dem gewuenschten Programm ausfuehren, sodass man dann den urspruenglichen Prozess mit dem urspruenglichen Programm hat und den neuen Prozess, der ein neues Programm ausfuehrt. (Siehe Codebeispel in meinem letzten Post).

So wie oben beschrieben laeuft auf unterster Betriebssystemebene jeder Start eines Programmes ab, anders geht's nicht. Das ist natuerlich kompliziert, deswegen gibt's Funktionen, die einem den Grossteil der Arbeit abnehmen, z.B. Pythons os.system. Die Doku sagt dazu:
Python Doku hat geschrieben:Execute the command (a string) in a subshell

d.h. via fork/exec* etc. wird eine Shell als Subprozess gestartet (sodass das urspruengliche Programm weiterlaeuft), und in dieser wiederum wir dein Befehl ausgefuehrt, als haettest du ihn in eine Shell getippt. D.h. du kannst Sachen benutzen, die Shell-spezifisch sind wie Wildcards (*, ?), Ausgabeumlenkung (>, <) und Shell-Kommandos (echo,...).

Meistens wird man exec* nicht anwenden, weil's wie gesagt sehr low level ist. (Macht aber Spass und man lernt was! :D ) Python bietet einem sehr viele andere Moeglichkeiten, Prozesse zu starten, u.a. eben os.system.
BlackJack

Beitragvon BlackJack » Montag 3. Juli 2006, 12:01

Die `exec*()` Funktionen sind Systemaufrufe, da werden die Parameter so übergeben wie Du sie angibst. Bei `os.system()` wird eine Shell gestartet und der wird die Zeichenkette als Kommando zum ausführen gegeben.

Das macht zum Beispiel einen Unterschied wenn Du als Argument einen Dateinamen mit Leer- oder Sonderzeichen übergibst. Bei `os.system()` musst Du dafür sorgen, dass die vor der Shell entsprechend "geschützt" werden. Und das ist Abhängig davon welche Shell das System benutzt. `echo %PATH%` oder `echo $PATH` haben unter Windows und Linux zum Beispiel jeweils andere Ausgaben zur Folge.
tobias.vdk
User
Beiträge: 19
Registriert: Mittwoch 23. November 2005, 16:51

Danke

Beitragvon tobias.vdk » Montag 3. Juli 2006, 12:22

Vielen Dank für eure Anworten!

Tschau Tobias

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder