2010-04-28 5 views
6

Ich habe ein kleines Befehlszeilenprogramm, das von stdin liest. in der Befehlszeile ich entweder laufen würde ...Kann ich eine geöffnete gzip-Datei mit Popen in Python verwenden?

./foo < bar 

oder ...

cat bar | ./foo 

Mit einer gziped Datei kann ich

zcat bar.gz | ./foo 

in Python ausführen ich tun kann. ..

Popen(["./foo", ], stdin=open('bar'), stdout=PIPE, stderr=PIPE) 

aber ich nicht

import gzip 
Popen(["./foo", ], stdin=gzip.open('bar'), stdout=PIPE, stderr=PIPE) 

kann ich

p0 = Popen(["zcat", "bar"], stdout=PIPE, stderr=PIPE) 
Popen(["./foo", ], stdin=p0.stdout, stdout=PIPE, stderr=PIPE) 

ich falsch bin etwas laufen aufzuwickeln mit? Warum kann ich gzip.open ('bar') nicht als Standard-Argument für Popen verwenden?

Antwort

4

weil die ‚stdin‘ und ‚stdout‘ der Subprozess Dateideskriptor nimmt (die eine Zahl ist), die eine Betriebssystem-Ressource ist. Dies wird durch die Tatsache maskiert, dass das Unterprozessmodul prüft, ob das Objekt ein 'fileno'-Attribut hat, und wenn es ein Objekt hat, wird es es verwenden.

Das ‚gzip‘ Objekt ist nicht etwas, das ein Betriebssystem zur Verfügung stellt. Eine offene Datei ist, ein Socket ist eine Pipe. Gzip-Objekt ist ein Objekt, das read() - und write() -Methoden, aber kein fileno-Attribut bereitstellt.

Sie bei der Kommunikation() -Methode von subprocess obwohl aussehen kann, können Sie es zu benutzen.

+0

Ja, ich bin eigentlich mit p = Popen ([...]) und dann p.communicate Lesung() [0]. Auch ist mein Programm nicht foo und meine Eingabedatei wird nicht aufgerufen bar ;-) Sie sind also gibt es keine einfache Lösung zu sagen genannt? Ich finde es seltsam, dass Popen ([ "./ foo",], stdin = gzip.open ('bar'), stdout = PIPE, stderr = PIPE) Werke (obwohl schlechte Ausgang zurückkehrt) und kein aufwirft Ausnahme. Es macht etwas damit, obwohl es möglicherweise kein Fileno-Attribut hat. –

+0

Die Attribute 'PIPE' und 'STDOUT' aus dem Subprozessmodul sind 'spezielle Konstanten'; Im Fall von stderr = STDOUT sagt die Konstante, dass die Datei, die an den Clientprozess übergeben werden soll, die gleiche sein sollte, die als stdout übergeben wird. Im Falle von PIPE wird eine neue Datei mit dem Befehl 'pipe()' des Betriebssystems erstellt, eine Hälfte der Pipe (die eigentlich aus 2 Zahlen besteht) wird an den Client-Prozess übergeben und Ihnen wird eine übergeben. Was auch immer in einen Teil geschrieben wird, kann von dem anderen gelesen werden. Sie können es nicht einfach beheben, mehr Programmierung wäre erforderlich. – ondra