Ich führe die folgende Version von Python aus:
%Vor% Ich führe den folgenden Python-Code aus, um Daten von einem Kind-Subprozess in die Standardausgabe zu schreiben und diese in eine Python-Variable namens metadata
:
Der Anwendungsfall ist wie folgt, um die ersten zehn Zeilen der Standardausgabe aus dem oben erwähnten Code-Snippet zu ziehen:
%Vor%Der Fehler wird angezeigt, wenn ich in head, awk, grep usw. pipere.
Das Skript endet mit dem folgenden Fehler:
%Vor%Ich hätte gedacht, das Schließen der Rohre wäre ausreichend, aber das ist offensichtlich nicht der Fall.
Hmmm. Ich habe schon einige "Broken pipe" -Strange mit Subprozess + gzip gesehen. Ich habe nie genau herausgefunden, warum es passierte, aber indem ich meinen Implementierungsansatz änderte, konnte ich das Problem vermeiden. Es sieht so aus, als ob Sie nur versuchen, einen Backend-Gzip-Prozess zu verwenden, um eine Datei zu dekomprimieren (wahrscheinlich, weil Pythons eingebautes Modul schrecklich langsam ist ... keine Ahnung warum, aber es ist definitiv).
Anstatt communicate()
zu verwenden, können Sie den Prozess stattdessen als vollständig asynchrones Backend behandeln und dessen Ausgabe nur so lesen, wie sie ankommt. Wenn der Prozess stirbt, kümmert sich das Subprozessmodul um die Reinigung für Sie. Der folgende Snippit sollte die gleiche Grundfunktionalität ohne Probleme mit defekten Pfeifen bieten.
Ich denke, diese Ausnahme hat nichts mit dem Subprozess -Aufruf oder seinen Dateideskriptoren zu tun (nachdem communicate aufgerufen wurde, wird das popen -Objekt geschlossen) . Dies scheint das klassische Problem beim Schließen von sys.stdout
in einer Pipe zu sein:
Obwohl es sich um einen 3 Jahre alten Käfer handelt, ist es nicht gelöst worden. Da sys.stdout.write(...)
auch nicht zu helfen scheint, können Sie auf einen Anruf auf niedrigerer Ebene zurückgreifen, probieren Sie dies aus:
Es gibt nicht genügend Informationen, um dies abschließend zu beantworten, aber ich kann einige fundierte Vermutungen anstellen.
Erstens sollte os.remove
definitiv nicht mit EPIPE versagen. Es sieht auch nicht so aus; Der Fehler ist close failed: [Errno 32] Broken pipe
, nicht remove failed
. Es sieht so aus, als ob close
fehlschlägt, nicht remove
.
Es ist möglich, das stdout einer Pipe zu schließen, um diesen Fehler zu erhalten. Wenn Daten gepuffert sind, löscht Python die Daten vor dem Schließen der Datei. Wenn der zugrunde liegende Prozess nicht mehr vorhanden ist, wird IOError / EPIPE ausgelöst. Beachten Sie jedoch, dass dies kein schwerwiegender Fehler ist: selbst wenn dies geschieht, ist die Datei immer noch geschlossen . Der folgende Code gibt ungefähr 50% der Zeit wieder und zeigt, dass die Datei nach der Ausnahme geschlossen wird. (Pass auf; ich denke, das Verhalten von bufsize hat sich in Versionen geändert.)
%Vor% Das ist rasant; es passiert nur zeitweise. Das könnte erklären, warum das Entfernen oder Hinzufügen des os.remove
-Aufrufs den Fehler beeinflusst.
Das heißt, ich kann nicht sehen, wie das mit dem Code, den Sie bereitgestellt haben, passieren würde, da Sie nicht auf stdin schreiben. Es ist das nächste, was ich ohne eine brauchbare Wiederholung erreichen kann, und vielleicht wird es dich in die richtige Richtung weisen.
Als Nebenbemerkung sollten Sie os.path.exists nicht überprüfen, bevor Sie eine Datei löschen, die möglicherweise nicht existiert. Wenn ein anderer Prozess die Datei zur gleichen Zeit löscht, führt dies zu Race Conditions. Tun Sie dies stattdessen:
%Vor% ... die ich normalerweise in eine Funktion wie rm_f
einpacke.
Schließlich, wenn Sie explizit einen Unterprozess abbrechen wollen, gibt es metadataPipes.kill
- das Schließen der Pipes wird das nicht tun - aber das erklärt den Fehler nicht. Auch, wenn Sie nur Gzip-Dateien lesen, ist das gzip-Modul viel besser als ein Subprozess. Ссылка