Frage

Ich habe einige Daten, die Ich mag würde, uuencode auf gzip und dann an die Standardausgabe zu drucken. Was ich im Grunde genommen haben, ist:

compressor = Popen("gzip", stdin = subprocess.PIPE, stdout = subprocess.PIPE)
encoder    = Popen(["uuencode", "dummy"], stdin = compressor.stdout)

So wie ich Daten zu dem Kompressor zuzuführen ist durch compressor.stdin.write (Sachen).

Was ich wirklich tun müssen, ist ein EOF an den Kompressor zu schicken, und ich habe keine Ahnung, wie es zu tun.

An einem gewissen Punkt habe ich versucht, compressor.stdin.close (), aber das funktioniert nicht - es funktioniert gut, wenn der Kompressor in eine Datei schreibt direkt, aber im obigen Fall wird der Prozess nicht beenden und Stände auf compressor.wait ().

Verbesserungsvorschläge? In diesem Fall ist gzip ein Beispiel und ich die Ausgabe von einem Prozess zum anderen Rohrleitungen.

etwas tun müssen, um wirklich mit

Hinweis: Die Daten, die wir komprimieren müssen, werden im Speicher nicht passen, so zu kommunizieren, ist nicht wirklich eine gute Wahl hier. Auch wenn ich nur laufen

compressor.communicate("Testing") 

, nachdem die zwei Zeilen weiter oben, es hängt immer noch mit dem Fehler

  File "/usr/lib/python2.4/subprocess.py", line 1041, in communicate
    rlist, wlist, xlist = select.select(read_set, write_set, [])
War es hilfreich?

Lösung

Ich vermute, dass das Problem mit der Reihenfolge, in der Sie die Rohre öffnen. UUEncode ist lustig ist, dass es jammern, wenn Sie es starten, wenn es in der richtigen Art und Weise kein eingehendes Rohr ist (versuchen Sie das verflixte Ding startet auf seine eigene in einem Popen Aufruf der Explosion mit nur PIPE als stdin und stdout zu sehen)

Versuchen Sie folgendes:

encoder = Popen(["uuencode", "dummy"], stdin=PIPE, stdout=PIPE)
compressor = Popen("gzip", stdin=PIPE, stdout=encoder.stdin)

compressor.communicate("UUencode me please")
encoded_text = encoder.communicate()[0]
print encoded_text

begin 644 dummy
F'XL(`%]^L$D``PL-3<U+SD])5<A-52C(24TL3@4`;2O+"!(`````
`
end

Sie haben recht, btw ... es keine Möglichkeit gibt, ein generisches EOF nach unten ein Rohr zu senden. Schließlich definiert jedes Programm wirklich seine eigene EOF. Die Art und Weise, es zu tun ist, das Rohr zu schließen, wie Sie versuchen, zu tun.

EDIT: Ich sollte über Uuencode klarer. Als Shell-Programm, dann ist es das Standardverhalten ist Konsole Eingang zu erwarten ist. Wenn Sie es ohne ein „live“ incoming Rohr ausführen, wird es blockiert für die Konsoleneingabe wartet. Durch den Encoder zweite Öffnung, bevor Sie Material auf der Kompressorrohr geschickt hatte, wurde der Encoder wartet Sperrung für Sie mit der Eingabe zu beginnen. Jerub richtig war, dass es etwas Sperrung war.

Andere Tipps

Das ist nicht die Art von Dingen sollten Sie direkt in Python tun, gibt es in Bezug auf die Exzentrizitäten, wie, was Arbeit, dass es eine viel bessere Idee, macht dies mit einer Schale zu tun. Wenn Sie nur subprocess.Popen verwenden. ( "Foo | bar", shell = True), dann umso besser

Was passiert sein könnte, ist, dass gzip nicht in der Lage gewesen, der Ausgabe aller Eingabe noch, und der Prozess wird nicht beendet, bis seine stdout schreibt abgeschlossen worden ist.

Sie können sehen, was Systemaufruf ein Prozess auf blockiert, wenn Sie strace verwenden. Verwenden Sie ps auxwf zu entdecken, welchen Prozess der gzip Prozess, dann strace -p $pidnum verwenden, um zu sehen, welches System nennt es ausführt. Beachten Sie, dass stdin ist FD 0 und stdout ist FD 1, werden Sie wahrscheinlich sehen, es zu lesen oder auf diese Datei-Deskriptoren zu schreiben.

, wenn Sie nur komprimieren möchten und müssen nicht die Datei-Wrapper mit dem zlib Modul betrachten

import zlib
compressed = zlib.compress("text")

ein Grund, warum die Shell = True und Unix-Rohre Vorschläge nicht funktionieren?

from subprocess import *

pipes = Popen("gzip | uuencode dummy", stdin=PIPE, stdout=PIPE, shell=True)
for i in range(1, 100):
    pipes.stdin.write("some data")
pipes.stdin.close()
print pipes.stdout.read()

scheint zu funktionieren

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top