os.system abwarten

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.
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

Hallo zusammen
Wenn ich in einem Programm mit os.system einen Befehl auf dem System ausführe (weil bspw. ein anderes Programm ein paar Daten produzieren muss, die ich mit dem aufrufenden Pythonskript bearbeiten will), dann scheint es mir so, als ob das Skript nicht darauf wartet bis das externe Programm zu Ende ist, sondern einfach weiter seine Instruktionen abarbeitet.
Wie kann ich erreichen, dass das Skript darauf wartet, dass das Programm das ich unter os.system starte auch wirklich beendet, bevor das Skript fortsetzt?

Vielen Dank für Hinweise.
[url=http://www.proandkon.com]proandkon.com[/url]
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Indem Du das subprocess-Modul verwendest ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo,

in der Dokumentation steht das eine oder andere Wort dazu. Interessant für dich ist auch der letzte Absatz mit dem Hinweis auf das subprocess-Modul. Das ist deutlich umfangreicher und sollte ``os.system`` vorgezogen werden.

Sebastian
Das Leben ist wie ein Tennisball.
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

Wie schreibe ich dann einen korrekten Befehl für subprocess.call?
Wenn der os.system Befehl so aussieht:

Code: Alles auswählen

os.system(self.vmd -dispdev text -eofexit < getCOM.vmd > ./sandbox/vmd-%s-com.log' % self.target)
?
[url=http://www.proandkon.com]proandkon.com[/url]
problembär

mzh hat geschrieben:

Code: Alles auswählen

os.system(self.vmd -dispdev text -eofexit < getCOM.vmd > ./sandbox/vmd-%s-com.log' % self.target)
Wenn Dein os.system-Befehl so aussieht, dann hast Du ein ganz anderes Problem: os.system() erwartet einen String. "self.vmd" kann eine Variable sein, aber dann müßte danach ' + "diesunddas" ' oder sowas kommen.
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

Ja, sorry das ist falsch abgetippt. Das Argument von os.system ist natürlich ein String.
Also, wie würde ich also den folgenden Befehl in subprocess.call übergeben? Ich hab vor allem Schwierigkeiten die Umleitungsklammern richtig mitzuteilen.

Code: Alles auswählen

os.system(self.vmd + ' -dispdev text -eofext < getCOM.vmd > ./sandbox/vmd-%s-com.log' % self.target)
wobei self.vmd auch ein String ist.

Ich habs mal an einer anderen Stelle versucht. Ursprünglich sah es so aus:

Code: Alles auswählen

os.system('./realign.py ../x_output/' + target[0:4] + '-out.pqr')
Nun habe ich, in Anlehnung an die Dokumentation zu subprocess folgendes probiert:

Code: Alles auswählen

p = subprocess.Popen('./realign.py ../x_output/' + target[0:4] + '-out.pqr')
Allerdings erhalte ich folgende Meldung:

Code: Alles auswählen

'No such file or directory'


<!-- The above is a description of an error in a Python program, formatted
     for a Web browser because the 'cgitb' module was enabled.  In case you
     are not reading this in a Web browser, here is the original traceback:

Traceback (most recent call last):
  File "/home/mzhpropka/public_html/a_content/runPDB2PQR.cgi", line 63, in ?
    p = subprocess.Popen('./realign.py ' +\
  File "/usr/lib/python2.4/subprocess.py", line 542, in __init__
    errread, errwrite)
  File "/usr/lib/python2.4/subprocess.py", line 975, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

-->
[url=http://www.proandkon.com]proandkon.com[/url]
problembär

Also, ich glaube, das Problem sind die Ausgabeumlenkungen, die da in dem Shell-Befehl sind.
Ich würde stattdessen über "os.popen()" die Ausgabe in das Python-Skript einlesen und von dort, also in Python, in eine log-Datei schreiben.

Auch das Einlesen über "<" würde ich eher in Python umsetzen.
BlackJack

@problembär: Aber bitte mit `subprocess` anstelle von `os.popen()`.
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

BlackJack hat geschrieben:@problembär: Aber bitte mit `subprocess` anstelle von `os.popen()`.
eben, also so

Code: Alles auswählen

p = subprocess.Popen('./realign.py ../x_output/' + target[0:4] + '-out.pqr')
?
[url=http://www.proandkon.com]proandkon.com[/url]
BlackJack

@mzh: Eher so wie in der Dokumentation beschrieben.
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

@blackjack:
In der Dokumentation steht das folgende:

Code: Alles auswählen

sts = os.system("mycmd" + " myarg")
==>
p = Popen("mycmd" + " myarg", shell=True)
sts = os.waitpid(p.pid, 0)[1]
was sind "mycmd" und "myarg"? Sind das Namen von Skripten? Oder Variablennamen von eingelesenen Skripten?
Was ich nicht aus der Dokumentation erkennen kann ist, wie man Umleitungen von Ausgaben am besten umsetzt, da wäre ich sehr froh um Hinweise.
[url=http://www.proandkon.com]proandkon.com[/url]
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

mzh hat geschrieben:was sind "mycmd" und "myarg"? Sind das Namen von Skripten? Oder Variablennamen von eingelesenen Skripten?
Wie kommst du denn darauf? Das sind Strings, nicht mehr, aber auch nicht weniger. Sinnvollerweise ist `myarg` ein Programm und `myarg` sind Argumente.
Ich bin mit dem Beispiel aber ueberhaupt nicht gluecklich, da es nicht die Alternative ohne `shell` aufzeigt *bugreport schreiben notier*.

Was du verwenden solltest ist:

Code: Alles auswählen

p = subprocess.Popen(['path/to/program', 'arg1', 'arg2'],
                      stdout=subprocess.PIPE,
                      stderr=subprocess.PIPE,
                      stdin=subprocess.PIPE)
stdout, stderr = p.communicate(input)
Wobei du std* nur uebergeben musst wenn du es brauchst, genauso musst du communicate kein `input` uebergeben, wenn du stdin nicht brauchst. Aber du solltest wirklich die Dokumentation lesen _und verstehen_.
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

cofi hat geschrieben:

Code: Alles auswählen

p = subprocess.Popen(['path/to/program', 'arg1', 'arg2'],
                      stdout=subprocess.PIPE,
                      stderr=subprocess.PIPE,
                      stdin=subprocess.PIPE)
stdout, stderr = p.communicate(input)
@ cofi: danke für das Beispiel.
Was ich allerdings nirgends finden kann ist wie ich mit den Umleitungen '<' und '>' umgehen soll.
Wenn ich auf der Shell also

Code: Alles auswählen

$ /path/to/program.sh < script.sh > output.dat
schreiben würde, würde das dann mit subprocess.Popen
so aussehen?

Code: Alles auswählen

p = subprocess.Popen(['/path/to/program.sh', 'script.sh', 'output.dat'],
                                      stdin='script.sh',
                                      stdout='output.dat'
[url=http://www.proandkon.com]proandkon.com[/url]
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

mzh hat geschrieben:Wenn ich auf der Shell also

Code: Alles auswählen

$ /path/to/program.sh < script.sh > output.dat
schreiben würde, würde das dann mit subprocess.Popen
so aussehen?

Code: Alles auswählen

p = subprocess.Popen(['/path/to/program.sh', 'script.sh', 'output.dat'],
                                      stdin='script.sh',
                                      stdout='output.dat'
Nein. Ungetestet(evtl sind die nested with's falsch):

Code: Alles auswählen

with open('script.sh'), open('output.dat', w) as in, out:
    p = subprocess.Popen(['/path/to/program.sh'],
                         stdin=in,
                         stdout=out)
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

cofi hat geschrieben:
mzh hat geschrieben:Wenn ich auf der Shell also

Code: Alles auswählen

$ /path/to/program.sh < script.sh > output.dat
schreiben würde, würde das dann mit subprocess.Popen
so aussehen?

Code: Alles auswählen

p = subprocess.Popen(['/path/to/program.sh', 'script.sh', 'output.dat'],
                                      stdin='script.sh',
                                      stdout='output.dat'
Nein. Ungetestet(evtl sind die nested with's falsch):

Code: Alles auswählen

with open('script.sh'), open('output.dat', w) as in, out:
    p = subprocess.Popen(['/path/to/program.sh'],
                         stdin=in,
                         stdout=out)
ich hab mir das eben gedacht, dass es wahrscheinlich so sein soll... und ist 'in' nicht ein keyword? Danke jedenfalls.
[url=http://www.proandkon.com]proandkon.com[/url]
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

Code: Alles auswählen

            
p = subprocess.Popen([self.vmd, '-dispdev text', '-eofexit'],
                    stdin=comScript,
                    stdout='./sandbox/vmd-%s-com.log' % self.target)


tja, wäre schön gewesen

Code: Alles auswählen

Traceback (most recent call last):
  File "/home/mzhpropka/public_html/a_content/runPDB2PQR.cgi", line 44, in ?
    ctrAlgn.writeCOM()
  File "/home/mzhpropka/public_html/a_content/realign.py", line 81, in writeCOM
    stdout='./sandbox/vmd-%s-com.log' % self.target)
  File "/usr/lib/python2.4/subprocess.py", line 533, in __init__
    (p2cread, p2cwrite,
  File "/usr/lib/python2.4/subprocess.py", line 830, in _get_handles
    p2cread = stdin.fileno()
AttributeError: 'str' object has no attribute 'fileno'
[url=http://www.proandkon.com]proandkon.com[/url]
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Würdest du die Dokumentation lesen, dann wüsstest du auch, warum das nicht funktionieren kann:
http://docs.python.org/library/subprocess.html hat geschrieben:stdin, stdout and stderr specify the executed programs’ standard input, standard output and standard error file handles, respectively. Valid values are PIPE, an existing file descriptor (a positive integer), an existing file object, and None.
Das Leben ist wie ein Tennisball.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

mzh hat geschrieben:ich hab mir das eben gedacht, dass es wahrscheinlich so sein soll... und ist 'in' nicht ein keyword? Danke jedenfalls.
Ja, `in` ist ein Keyword. Das musst du dann eben durch `in_` ersetzen.
Und wenn du dir gedacht hast, dass es "wahrscheinlich so sein soll", warum machst du es in deinem Versuch dann nicht so?
syntor
User
Beiträge: 88
Registriert: Donnerstag 2. Dezember 2010, 03:56

EyDu hat geschrieben:Würdest du die Dokumentation lesen, dann wüsstest du auch, warum das nicht funktionieren kann:
http://docs.python.org/library/subprocess.html hat geschrieben:stdin, stdout and stderr specify the executed programs’ standard input, standard output and standard error file handles, respectively. Valid values are PIPE, an existing file descriptor (a positive integer), an existing file object, and None.
Oder ganz einfach cofi's Beispiel beachten.
Antworten