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

Ich glaub ich habs jetzt endlich mehr oder weniger hingekriegt. Macht die folgende Art das externe Programm auszuführen ungefähr Sinn?

Code: Alles auswählen

>>> vmdCmd
'/home/mzhpropka/software/vmd-bin-dir/vmd'
>>> vmdInp
'/home/mzhpropka/public_html/a_content/sandbox/vmd_test.vmd'
>>> p2 = subprocess.Popen(vmdCmd + ' -dispdev text' + ' < ' + vmdInp, shell=True)
>>> Info) VMD for LINUX, version 1.8.7 (August 1, 2009)
Info) http://www.ks.uiuc.edu/Research/vmd/                         
Info) Email questions and bug reports to vmd@ks.uiuc.edu           
Info) Please include this reference in published work using VMD:   
Info)    Humphrey, W., Dalke, A. and Schulten, K., `VMD - Visual   
Info)    Molecular Dynamics', J. Molec. Graphics 1996, 14.1, 33-38.
Info) -------------------------------------------------------------
Info) Multithreading available, 1 CPU detected.
Info) Free system memory: 746MB (74%)
Info) No CUDA accelerator devices available.
invalid command name "-dispdev"
/home/mzhpropka/software/vmd-lib-dir/scripts/tcl8.5 /home/mzhpropka/software/vmd-lib-dir/scripts /home/mzhpropka/software/lib /Projects/johns/tcl/8.5.6/lib_LINUX/lib /home/mzhpropka/software/vmd-lib-dir/scripts/vmd /home/mzhpropka/software/vmd-lib-dir/plugins/LINUX/tcl /home/mzhpropka/software/vmd-lib-dir/plugins/noarch/tcl /home/mzhpropka/software/vmd-lib-dir/scripts/la1.0
/home/mzhpropka/software/vmd-lib-dir/scripts/tcl8.5 /home/mzhpropka/software/vmd-lib-dir/scripts /home/mzhpropka/software/lib /Projects/johns/tcl/8.5.6/lib_LINUX/lib /home/mzhpropka/software/vmd-lib-dir/scripts/vmd /home/mzhpropka/software/vmd-lib-dir/plugins/LINUX/tcl /home/mzhpropka/software/vmd-lib-dir/plugins/noarch/tcl /home/mzhpropka/software/vmd-lib-dir/scripts/la1.0 /home/mzhpropka/software/vmd-lib-dir/scripts/orient
VMD is loading the file
Info) Using plugin pdb for structure file 1AVD.pdb
Info) Using plugin pdb for coordinates from file 1AVD.pdb
Info) Determining bond structure from distance search ...
Info) Finished with coordinate file 1AVD.pdb.
Info) Analyzing structure ...
Info)    Atoms: 2022
Info)    Bonds: 2026
Info)    Angles: 0  Dihedrals: 0  Impropers: 0  Cross-terms: 0
Info)    Bondtypes: 0  Angletypes: 0  Dihedraltypes: 0  Impropertypes: 0
Info)    Residues: 287
Info)    Waters: 37
Warning) Unusual bond between residues:  17 (protein) and 600 (none)
Info)    Segments: 1
Info)    Fragments: 41   Protein: 2   Nucleic: 0
0
atomselect0
Info) Opened coordinate file 1AVD-rew.pdb for writing.
Info) Finished with coordinate file 1AVD-rew.pdb.
Info) VMD for LINUX, version 1.8.7 (August 1, 2009)
Info) Exiting normally.

>>> 
Wenn ich allerdings 'shell=False' setze, dann kriege ich

Code: Alles auswählen

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  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
>>> 
und in der Dokumentation steht, dass 'shell' normalerweise nicht benötigt wird. Woran kann es liegen, dass der Befehl bei mir nur mit 'shell=True' funktioniert?
[url=http://www.proandkon.com]proandkon.com[/url]
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Da du offensichtlich nicht liest und umsetzt was andere schreiben, solltest du einfach den Thread noch einmal von vorne durcharbeiten und die Beiträge vestehen und entsprechend auf dein Problem anwenden.
Das Leben ist wie ein Tennisball.
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

Ich habe jetzt versucht soviel zu dem Thema zu verstehen wie möglich und dazu auch einige simple Beispiele versucht.
Bspw. das folgende:
Ich will mir den Inhalt des Verzeichnisses anzeigen lassen. Die Anzeige wird in ein File 'lsout.dat' umgeleitet.
Der Shellbefehl 'ls' steht in einem File 'lsCmd.sh'. Für 'ls' soll die '-l' Option verwendet werden.

Das 'lsCmd.sh' File sieht so aus:

Code: Alles auswählen

#!/bin/bash
ls -l
Nun der Pythonteil:

Code: Alles auswählen

import subprocess
lsproc = subprocess.Popen(['./lsCmd.sh'], stdout=subprocess.PIPE, shell=False)
lsout = open('lsout.dat', 'w')
lsout.write(lsproc.stdout.read())
lsout.close()
Im 'lsout.dat' File steht nun der Inhalt des Verzeichnisses. In meinem Fall sieht es so aus, dass ich ein Programm starten möchte, welches dann ein File mit Anweisungen ausführt, bspw. gnuplot.
Das Anweisungs-File 'sin_cos.gnu' könnte so aussehen:

Code: Alles auswählen

set terminal postscript;
set output 'sin_cos.ps';
plot sin(x), cos(x);
quit;
Auf der Shell würde ich das so aufrufen:

Code: Alles auswählen

$ gnuplot < sin_cos.gnu
So erhalte ich das 'sin_cos.ps' File.
Mit subprocess.Popen würde ich das jetzt so machen:

Code: Alles auswählen

import subprocess
gnup = subprocess.Popen(['gnuplot', 'sin_cos.gnu'], shell=False)
Das schreibt mir das 'sin_cos.ps' File. Ich versuche das jetzt auf meine Situation anzuwenden.
[url=http://www.proandkon.com]proandkon.com[/url]
Benutzeravatar
snafu
User
Beiträge: 6862
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

`sin_cos.gnu` ist kein Argument von `gnuplot`, sondern es ist eine Umleitung, die den Dateiinhalt von `sin_cos.gnu` in den `stdin` vom Prozess `gnuplot` schreibt. Du solltest das dann auch entsprechend in deinem `subprocess`-Aufruf so umsetzen.

Übrigens, du kannst `Popen()` bereits ein Dateiobjekt für die Umleitung eines Datenstroms mitgeben und musst daher nicht den Umweg über `PIPE` gehen.
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

@snafu:
Ich habe jetzt nur diese weitere Möglichkeit gefunden, ich versteh leider nicht genau wie du meinst.

Code: Alles auswählen

[mzh] @ ~/programming/subpro $ python
Python 2.6.1 (r261:67515, Feb 11 2010, 15:47:53) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> gnuproc = subprocess.Popen(['gnuplot'], stdin=subprocess.PIPE, shell=False)
>>> gnuinp = open('sin_cos.gnu', 'r')
>>> gnuinp
<open file 'sin_cos.gnu', mode 'r' at 0x406750>
>>> gnuproc.stdin.write(gni.read())
>>> 
[url=http://www.proandkon.com]proandkon.com[/url]
BlackJack

@mzh: Du kannst bei `Popen()` anstelle von der `PIPE`-Konstante auch eine geöffnete Datei übergeben. Was ist denn daran jetzt schon wieder nicht zu verstehen!?
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

achso, also

Code: Alles auswählen

[mzh] @ ~/programming/subpro $ python
Python 2.6.1 (r261:67515, Feb 11 2010, 15:47:53) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> gnuproc = subprocess.Popen(['gnuplot'], stdin=open('gnuinp.gnu', 'r'), shell=False)
>>>
[url=http://www.proandkon.com]proandkon.com[/url]
problembär

mzh hat geschrieben:Auf der Shell würde ich das so aufrufen:

Code: Alles auswählen

$ gnuplot < sin_cos.gnu
So erhalte ich das 'sin_cos.ps' File.
Mit subprocess.Popen würde ich das jetzt so machen:

Code: Alles auswählen

import subprocess
gnup = subprocess.Popen(['gnuplot', 'sin_cos.gnu'], shell=False)
Was snafu meint, ist: Wo ist denn da das "<" aus dem obigen Shell-Befehl?
Was Du da machst ist doch eine Umleitung der Eingabe:

http://tldp.org/LDP/abs/html/io-redirection.html

So, und ob "subprocess" das mitmacht, wenn Du das "<" einfach als Argument mitgibst, weiß ich nicht. Deswegen benutze und empfehle ich bei solchen komplizierten Shell-Kommandos ja eben doch eher "os.system()" und "os.popen()". Hier wäre das einfach:

Code: Alles auswählen

os.system("gnuplot < sin_cos.gnu")
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Genau dafür sind die `std*` Parameter des `subprocess.Popen`-Aufrufs da. Und selbst wenn man bei Shellbefehlen bleiben will, gibt es immernoch den Shell-Parameter. Es gibt schlichtweg keinen Grund weiterhin die Funktionen des `os` Moduls zu nutzen.

@mzh: Nein. Du solltest die Datei explizit schliessen und dich nicht auf den GC verlassen.
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

problembär hat geschrieben:

Code: Alles auswählen

os.system("gnuplot < sin_cos.gnu")
Wenn das in meinem Fall funktionieren würde, hätte ich mir ja den ganzen Thread sparen können. Das habe ich natürlich schon versucht, das Problem, soweit ich es verstehe, ist in diesem Fall aber, dass der gnuplot Prozess dabei in einer neuen Shell startet. Dh. Python selber setzt die Abarbeitung seines Skriptes fort, obwohl die Ausgabe aus dem Prozess von os.system(...) für die Fortsetzung des Skriptes benötigt wird. Dh. Python sollte "warten", bis der Flow of Control wieder zurück zum Skript kommt.
@cofi: So?

Code: Alles auswählen

[mzh] @ ~/programming/subpro $ python
Python 2.6.1 (r261:67515, Feb 11 2010, 15:47:53)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> inFile = open('gnuinp.gnu', 'r')
>>> gnuproc = subprocess.Popen(['gnuplot'], stdin=inFile.read(), shell=False)
>>> inFile.close()
Hab jetzt nicht getestet, ob da stehen soll 'stdin=inFile.read()', oder bloss 'stdin=inFile'.
[url=http://www.proandkon.com]proandkon.com[/url]
Benutzeravatar
snafu
User
Beiträge: 6862
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Code: Alles auswählen

with open('sin_cos.gnu') as infile:
    subprocess.call('gnuplot', stdin=infile)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nein, so wie ich es in meinem Beispiel gezeigt habe, damit der Code da ran kommt musst du das in ein `try ... finally` Konstrukt wickeln.

In dem Code hast du schon wieder keine File-Objekt mehr sondern einen String, also ja ohne `.read()`.
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

mzh hat geschrieben:Hab jetzt nicht getestet, ob da stehen soll 'stdin=inFile.read()', oder bloss 'stdin=inFile'.
Und warum nicht?
Benutzeravatar
snafu
User
Beiträge: 6862
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Es hat beim Helfen immer so einen faden Beigeschmack, wenn man den Eindruck hat, dass der Fragesteller zu keinem Zeitpunkt so wirklich zu wissen scheint, was er da überhaupt gerade tut. :(
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

snafu hat geschrieben:Es hat beim Helfen immer so einen faden Beigeschmack, wenn man den Eindruck hat, dass der Fragesteller zu keinem Zeitpunkt so wirklich zu wissen scheint, was er da überhaupt gerade tut. :(
Es erscheint mir angebracht zu bemerken, dass ich für Hinweise sehr froh und dankbar bin. Auf Kommentare, die mir unterstellen ich versuche der Beschäftigung mit der Materie auszuweichen muss ich nicht eingehen. Ich finde ein Forum eine sehr gute Form sich zu Wissen auszutauschen und ich habe hier schon oft den richtigen Hinweis gefunden, wie ein Problem zu lösen sei.
[url=http://www.proandkon.com]proandkon.com[/url]
Benutzeravatar
snafu
User
Beiträge: 6862
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich meinte nicht so sehr, dass du es dir gemütlich machen willst und hoffst, alles vorgekaut zu bekommen. Du probierst ja durchaus Sachen selbst aus. Wenn man sich mal etwas blöde auf neuem Terrain anstellt, ist das ja durchaus entschuldbar. Bei dir hat man aber den Eindruck, dass du Trial-and-Error mäßig so lange herum probierst bis du irgendwann ein funktionierendes Ergebnis hast. Der Anstoß zu meinem Kommentar war der Moment als du das Ergebnis von `.read()` an `stdin` übergeben wolltest. Ist dir bewusst, was die `read()`-Methode eines Dateiobjekts zurück gibt? Wenn ja, dann vergleiche mal den Typen des Rückgabewertes mit dem Typen, welcher von `Popen()` (s. Doku) erwartet wird. Ein solches Vorgehen nenne ich halt "planlos". Nichts für ungut, ich bin ganz zu Anfang teilweise auch so vorgegangen. Ich will dich eigentlich nur ermuntern, wenn Begriffe wie "Dateiobjekt" fallen, dich auch mal damit zu beschäftigen, was ein Dateiobjekt genau ist und wie es in der Praxis verwendet wird. Um alle Informationen über die Teilbereiche eines Anwendungsgebiets durchzugehen, braucht man durchaus auch schon einmal mehr als nur einen Abend an Recherche. So ist das nunmal. Dafür weiß man am Ende aber zumindest relativ gut, was man da tut und warum man es tut. ;)
mzh
User
Beiträge: 295
Registriert: Dienstag 3. März 2009, 15:27
Wohnort: ZH

Das Leben ist bekanntlich kein Ponyhof, da geb ich dir vorbehaltlos Recht.
[url=http://www.proandkon.com]proandkon.com[/url]
problembär

mzh hat geschrieben:

Code: Alles auswählen

$ gnuplot < sin_cos.gnu
So erhalte ich das 'sin_cos.ps' File.
mzh hat geschrieben:
problembär hat geschrieben:

Code: Alles auswählen

os.system("gnuplot < sin_cos.gnu")
Wenn das in meinem Fall funktionieren würde, hätte ich mir ja den ganzen Thread sparen können. Das habe ich natürlich schon versucht, das Problem, soweit ich es verstehe, ist in diesem Fall aber, dass der gnuplot Prozess dabei in einer neuen Shell startet. Dh. Python selber setzt die Abarbeitung seines Skriptes fort, obwohl die Ausgabe aus dem Prozess von os.system(...) für die Fortsetzung des Skriptes benötigt wird. Dh. Python sollte "warten", bis der Flow of Control wieder zurück zum Skript kommt.
Ich bastel ja auch ganz gern herum. Also, warum dann nicht:

Code: Alles auswählen

import os
import time
os.system("gnuplot < sin_cos.gnu")
while not os.path.isfile("sin_cos.ps"):
    time.sleep(0.2)
? Würde auch gut zum Threadtema passen : "os.system abwarten". :wink:

Gruß

P.S.: Wenn Dein Problem wirklich die Subshell ist, kannst Du statt "os.system()" auch mal "os.execl()" und weitere probieren (Infos in "pydoc.os").
Bei der auszuführenden Datei ist dabei offenbar der vollständige Pfad anzugeben.
Beispielsweise geht bei mir folgendes:

Code: Alles auswählen

import os
os.execl("/bin/ls", "")
BlackJack

@problembär: Das wartet nur solange bis die Datei existiert. Ich nehme doch mal an das die Datei auch *vollständig* sein sollte bevor das Programm weiter läuft. Sollte es die Datei schon vorher gegeben haben, wird auch nicht gewartet. Und es verwendet `os.system()`. :roll:
problembär

BlackJack hat geschrieben:@problembär: Das wartet nur solange bis die Datei existiert. Ich nehme doch mal an das die Datei auch *vollständig* sein sollte bevor das Programm weiter läuft. Sollte es die Datei schon vorher gegeben haben, wird auch nicht gewartet. Und es verwendet `os.system()`. :roll:
Natürlich kann man auch noch die Dateigröße prüfen oder z.B. dem Dateinamen einen Zusatz mitgeben, um sie eindeutig als die von dem system-Befehl angelegte zu identifizieren.
Mit etwas Phantasie wäre das doch wohl klar.
Antworten