Hey Leute,
Ich würde gerne in meinem Python Programm ein anderes Programm aufrufen und davon den output einfangen und in einer Variable speichern!
Ich habe jetzt eine halbe Stunde gesucht und die Module posix, subprocess und os ausprobiert, doch ich bekomme es einfach nicht gebacken!
Die Sache ist doch bestimmt ganz einfach oder?
so long,
Samy
Ausgabe von Programm einlesen
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Hallo,
das kannst Du ganz einfach mit popen() machen! Hab grad kein Python zur Verfügung, aber ist echt einfach. Guck mal in der Doku bei "os" nach. iirc steht da was dazu. Ist eigentlich wie ne Datei, also ca. folgendes Schema (ungetestet):
das kannst Du ganz einfach mit popen() machen! Hab grad kein Python zur Verfügung, aber ist echt einfach. Guck mal in der Doku bei "os" nach. iirc steht da was dazu. Ist eigentlich wie ne Datei, also ca. folgendes Schema (ungetestet):
Code: Alles auswählen
p = popen("dein_programm")
out = p.read()
p.close()
- Rebecca
- User
- Beiträge: 1662
- Registriert: Freitag 3. Februar 2006, 12:28
- Wohnort: DN, Heimat: HB
- Kontaktdaten:
Ab Python 2.4 sollte man subprocess verwenden: [wiki]Neue Features#Subprocess[/wiki]
Offizielles Python-Tutorial (Deutsche Version)
Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
-
- User
- Beiträge: 44
- Registriert: Donnerstag 26. April 2007, 19:23
Mit subprocess würde ich es gerne machen, doch folgender Code funktioniert nicht:
Die Ausgabe ist:
Was mache ich da falsch?
so long,
Samy
Code: Alles auswählen
process = subprocess.Popen(["du", "--max-depth=0 "+dir], stdout=subprocess.PIPE)
process.wait()
print process.stdout.read()
Code: Alles auswählen
156720 .
so long,
Samy
- Rebecca
- User
- Beiträge: 1662
- Registriert: Freitag 3. Februar 2006, 12:28
- Wohnort: DN, Heimat: HB
- Kontaktdaten:
Bei mir klappt es so, man beachte den Unterschied bei der Parameteruebergabe fuer du:
Code: Alles auswählen
>>> process = subprocess.Popen(["du", "--max-depth=0", "/home/rbreu"], stdout=subprocess.PIPE)
>>> process.wait()
>>> print process.stdout.read()
18360840 /home/rbreu
Offizielles Python-Tutorial (Deutsche Version)
Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
-
- User
- Beiträge: 44
- Registriert: Donnerstag 26. April 2007, 19:23
ok, danke!
Es lag an der übergabe der Argumente!
Es lag an der übergabe der Argumente!
-
- User
- Beiträge: 44
- Registriert: Donnerstag 26. April 2007, 19:23
Hm, ich habe gerade wieder ein Problem:
Ich will gerne alle Dateien die es in einem Verzeichnis + Unterverzeichnissen gibt einlesen. Das geht auf der Konsole ja ganz einfach mit:
Insgesamt erzeugt das 2006 Zeilen (mit einem "wc -l" gemessen) und funktioniert auf der Konsole wunderbar.
Wenn ich nun jedoch folgenden Python Code probiere das gleiche machen zu lassen, macht er einfach nichts und das für mehrere Stunden:
Wenn ich allerdings das Suchmuster etwas eingrenze, dann geht das ganze wunderbar. Ich habe es mit "*html" als Suchmuster versucht was mit 434 Ergebnisse liefert. Das funktioniert dann sowohl auf der Shell als auch in Python wunderbar!
Irgendwas läuft da schief!
Ich will gerne alle Dateien die es in einem Verzeichnis + Unterverzeichnissen gibt einlesen. Das geht auf der Konsole ja ganz einfach mit:
Code: Alles auswählen
find /directory -name '*'
Wenn ich nun jedoch folgenden Python Code probiere das gleiche machen zu lassen, macht er einfach nichts und das für mehrere Stunden:
Code: Alles auswählen
import subprocess
dir = "/directory"
process = subprocess.Popen(["find", dir, "-name", "*"], stdout=subprocess.PIPE)
process.wait()
print process.stdout.read()
Irgendwas läuft da schief!
Hallo
ich vermute, dass Du den Parameter * noch in Hochkommas schreiben musst also: "'*'".
Da Du ja bei deinem ursprünglichen Befehl auch den * in Hochkomma hast.
Grüße
Pug
ich vermute, dass Du den Parameter * noch in Hochkommas schreiben musst also: "'*'".
Da Du ja bei deinem ursprünglichen Befehl auch den * in Hochkomma hast.
Code: Alles auswählen
import subprocess
dir = "/directory"
process = subprocess.Popen(["find", dir, "-name", "'*'"], stdout=subprocess.PIPE)
process.wait()
print process.stdout.read()
Grüße
Pug
Die Vermutung habe ich auch, denn:
Und diese Meldung kommt nicht auf `process.stdout` an, sondern auf `process.stderr`. Letzteres liest Du nie aus, damit beendet sich der Prozess nie, und das wiederum führt dazu, dass Du beim Lesen von `process.stdout` bis zum Sankt Nimmerleins-Tag warten kannst.
Code: Alles auswählen
bj@s8n:~$ find /directory -name *
find: paths must precede expression
Usage: find [-H] [-L] [-P] [path...] [expression]
Das sieht nur auf der Shell so aus (da ist der Asterik ja ein Sonderzeichen und muss korrekt gequoted werden). Allerdings umgeht subprocess die Shell und nutzt fork/execvp, um ein neuen Prozess zu starten. Die Argumente in der Liste kommen genau so, wie sie dastehen, bei find an:
Es funktioniert also auch ohne Quoting. Im Gegenteil, ich glaube sogar, dass es mit Hochkomma gar nicht funktioniert, weil find dann nach Dateien sucht, die dieses Hochkomma enthalten (find sieht das Hochkomma ja, da die Shell nicht dazwischen funkt).
Edit: wait scheint bei meinen Versuchen ebenfalls zu hängen, allerdings sieht subprocess ja eigentlich auch eine andere Methode vor, um mit dem Unterprozess zu kommunizieren:
Damit funktioniert es auch.
Code: Alles auswählen
[lunar@nargond]-[10:10:34] >> /home/lunar
[2]--> subprocess.call(['find', '/home/lunar', '-name', '*'])
/home/lunar
/home/lunar/.htoprc
/home/lunar/Kalender.ics~
/home/lunar/.recently-used.xbel
/home/lunar/.bogofilter
/home/lunar/.bogofilter/wordlist.db
/home/lunar/.ktorrent.lock
...
Edit: wait scheint bei meinen Versuchen ebenfalls zu hängen, allerdings sieht subprocess ja eigentlich auch eine andere Methode vor, um mit dem Unterprozess zu kommunizieren:
Code: Alles auswählen
process = subprocess.Popen(['find', '/directory', '-name', '*'], stdout=subprocess.PIPE)
stdout = process.communicate()[0]
print stdout
Zuletzt geändert von lunar am Sonntag 23. September 2007, 09:29, insgesamt 2-mal geändert.
-
- User
- Beiträge: 44
- Registriert: Donnerstag 26. April 2007, 19:23
Super, so funktioniert es!
Vielen Dank für die super Hilfe hier!
Nochmal ne kurze Rückfrage: Es ist also generell besser den Output mit "process.communicate()[0]" zu holen, anstatt erst "process.wait()" zu machen und dann den Output anzufragen?
Vielen Dank für die super Hilfe hier!
Nochmal ne kurze Rückfrage: Es ist also generell besser den Output mit "process.communicate()[0]" zu holen, anstatt erst "process.wait()" zu machen und dann den Output anzufragen?
Nein.
Um richtig große Mengen an Daten einzulesen, würde sich also vielleicht eher sowas anbieten:
Dadurch sparst du dir das Anlegen einer endlosen Liste. Wenn der Speicherverbrauch allerdings egal ist, dann kannst imho auch communicate verwenden.
Wenn du große Mengen an Daten aus der Pipe lesen willst, dann solltest du communicate nicht nutzen. wait() funktioniert offenbar allerdings auch nicht. Ich denke mal, dass das daran liegt, dass der Pufferspeicher der Pipe zuläuft und find so nichts mehr auf stdout schreiben kann und deswegen einfriert, bis du aus stdout liest.Python Doku hat geschrieben:Note: The data read is buffered in memory, so do not use this method if the data size is large or unlimited.
Um richtig große Mengen an Daten einzulesen, würde sich also vielleicht eher sowas anbieten:
Code: Alles auswählen
process = subprocess.Popen(['find', '/directory', '-name', '*'], stdout=subprocess.PIPE, bufsize=1)
while True:
line = process.stdout.readline()
if not line:
break
# die Zeile hier verarbeiten
Doch, wahrscheinlich schon Hab irgendwie nicht daran gedacht...BlackJack hat geschrieben:Direkt über `process.stdout` iterieren geht nicht?
Auf die Uhrzeit kann ich das jetzt nicht schieben... aber vielleicht auf den fehlenden Kaffee heute Nachmittag