subprocess stdin schreiben

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.
Antworten
buiz
User
Beiträge: 3
Registriert: Montag 24. Januar 2011, 17:37

Hallo,

meine Frage bezieht sich auf das subprocess-Modul:
Kann ich anstatt wie üblich aus stdin des subprocess zu lesen auch dort hineinschreiben?
Dementsprechend würde ich auch gerne aus stdout lesen können.
Beispiel: Ich mache einen subprocess "python.exe" , gebe dort innerhalb der dann geöffneten Python-Eingabeaufforderung einen Befehl wie "print "hallo"" ein und lese dann das Ergebnis aus.
Dies könnte auch über sys.stdin und sys.stdout gehen, damit hätte ich kein Problem.
PS: Ich nutze Windows 7, falls das wichtig ist.
(Nachtrag: ich meine natürlich stdin schreiben, ohne mit der Tastatur zu schreiben, dies müsste dann eventuell simuliert werden?)

Vielen Dank und viele Grüße
BlackJack

@buiz: Für solche Interaktionen würde man eher das `pexpect`-Modul verwenden. Das täuscht dem anderen Programm vor es wäre mit einem Terminal verbunden.
buiz
User
Beiträge: 3
Registriert: Montag 24. Januar 2011, 17:37

Vielen Dank für die schnelle Antwort.
Ich habe aber festgestellt, dass pexpect nur für UNIX-artige Systeme verwendbar ist
(Modul resource fehlt) und auch Ports für Windows wie winpexpect oder wpexpect nicht funktionieren (da pywintypes fehlt?).
Weiß jemand hier eine Lösung oder ein anderes Modul unter Windows mit dem gleichen Zweck?
(Nachtrag: Ich will es nicht unter cygwin installieren, da das ja wieder eine andere Umgebung ist!)
deets

Ich glaube du verwechselst hier so einiges. Sinn und Zweck von stdin und stdout eines Kind-Prozesses ist es immer, in den einen (stdin) zu schreiben, und den anderen (stdout, und stderr) zu lesen. Und die Parameter stdin/stdout/stderr erlauben genau das: wenn du sowas machst wie

Code: Alles auswählen

p = subprocess.Popen([command], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
stdout, stderr = p.communicate("Etwas das in stdin geschrieben wird")
dann sollte genau das passieren, was du willst. Wenn du kannst, solltest du communicate verwenden, das ist am einfachsten. Alternativ kannst du (bei langen oder von den Ausgaben abhaengigen Eingaben) ueber die file-like Objecte p.stdout, p.stdin & p.stderr gehen.

Aber unter Umstaenden kommst du um pexpect (bzw. dessen Windows-Analogon) nicht herum, wenn die Ausgabe sonst gebuffert ist, und du nicht das richtige Verhalten bekommst. Da kenne ich mich mit Windows einfach nicht genug aus.
buiz
User
Beiträge: 3
Registriert: Montag 24. Januar 2011, 17:37

Genau, ich habe schon oft versucht, das mit subprocess zum Laufen zu bringen,
aber ich habe immer Probleme wie: nach communicate() wird die PIPE geschlossen
oder bei stdout.read() wird kein EOF erreicht etc., so dass ich immer gescheitert bin.
Entweder mache ich es einfach falsch (wie kann ich das denn richtig machen unter Windows?) oder
es funktioniert so einfach nicht, zum Beispiel weil die Ausgabe gebuffert ist wie du sagst.
Dann bräuchte ich eben ein pexpect für Windows, was ich leider nicht wirklich finden kann.
deets

Du widersprichst dir. Wenn du bei communicate ein pipe closed (also EOF) bemaengelst, und das bei stdin.read keines vorkommt ebenfalls, dann weisst du nicht, was du willst. Beides zusammen geht nunmal nicht - EOF und kein EOF.

Wie waere es, wenn du mal konkret wirst, was dein Kommando bekommen soll, und was es ausspuckt.
Antworten