Ich habe ein sehr einfaches Python 3-Skript:
f1 = open('a.txt', 'r')
print(f1.readlines())
f2 = open('b.txt', 'r')
print(f2.readlines())
f3 = open('c.txt', 'r')
print(f3.readlines())
f4 = open('d.txt', 'r')
print(f4.readlines())
f1.close()
f2.close()
f3.close()
f4.close()
Aber es heißt immer:
IOError: [Errno 32] Broken pipe
Ich habe im Internet alle komplizierten Möglichkeiten gesehen, dies zu beheben, aber ich habe diesen Code direkt kopiert, sodass ich denke, dass etwas mit dem Code nicht stimmt und nicht mit Pythons SIGPIPE.
Ich leite die Ausgabe um. Wenn das obige Skript "open.py" heißt, lautet mein Befehl zum Ausführen:
open.py | othercommand
python
python-3.x
sigpipe
JOHANNES_NYÅTT
quelle
quelle
print(f1.readlines())
a.txt
und ein Schreiben vonstdout
. Versuchen Sie möglicherweise, diese in separate Zeilen aufzuteilen, damit Sie sehen können, welche Operation die Ausnahme auslöst. Wennstdout
es sich um eine Pipe handelt und das Leseende geschlossen wurde, kann dies denEPIPE
Fehler erklären .print
Anruf der Schuldige ist. @ JOHANNES_NYÅTT, können Sie klarstellen, wie Sie Ihr Python-Skript starten? Leiten Sie die Standardausgabe irgendwo um?Antworten:
Ich habe das Problem nicht reproduziert, aber vielleicht würde diese Methode es lösen: (Zeile für Zeile schreiben,
stdout
anstatt zu verwendenprint
)Sie könnten das kaputte Rohr fangen? Dadurch wird die Datei
stdout
zeilenweise geschrieben, bis die Pipe geschlossen wird.Sie müssen auch sicherstellen, dass
othercommand
die Pipe aus der Pipe gelesen wird, bevor sie zu groß wird - /unix/11946/how-big-is-the-pipe-bufferquelle
print
Aufruf zu tun hat , nicht mit dem Lesen der Dateien).Das Problem ist auf die SIGPIPE-Behandlung zurückzuführen. Sie können dieses Problem mit dem folgenden Code lösen:
Hier finden Sie Hintergrundinformationen zu dieser Lösung. Besser hier antworten .
quelle
Zu bringen , Alex L. hilfreiche Antwort , Akhan der hilfreiche Antwort und Blckknght des hilfreiche Antwort zusammen mit einigen zusätzlichen Informationen:
Das Standard-Unix-Signal
SIGPIPE
wird an einen Prozess gesendet, der in eine Pipe schreibt , wenn (nicht mehr) kein Prozess von der Pipe gelesen wird .head
von Natur aus , hören auf, vorzeitig aus einer Pipe zu lesen, sobald sie genügend Daten erhalten haben.In der Standardeinstellung - das heißt, wenn der Schreibvorgang nicht explizit Fall
SIGPIPE
- der Schreibvorgang wird einfach beendet , und ihr Exit - Code ist auf141
, die wie folgt berechnet wird128
(um Signal Beendigung durch das Signal im Allgemeinen) +13
(SIGPIPE
‚s spezifischen Signalnummer ) .Durch Design, aber Python selbst einfängt
SIGPIPE
und übersetzt sie in eine PythonIOError
- Instanz miterrno
Werterrno.EPIPE
, so dass ein Python - Skript , um es zu fangen, wenn es so wählt - siehe Alex L. Antwort , wie das zu tun.Wenn ein Python- Skript es nicht abfängt , gibt
IOError: [Errno 32] Broken pipe
Python eine Fehlermeldung aus und beendet das Skript mit dem Exit-Code1
- dies ist das Symptom, das das OP gesehen hat.In vielen Fällen ist dies eher störend als hilfreich . Daher ist es wünschenswert, zum Standardverhalten zurückzukehren :
Die Verwendung des
signal
Moduls ermöglicht genau das, wie in Akhans Antwort angegeben .signal.signal()
nimmt ein Signal als erstes Argument und einen Handler als zweites; Der spezielle HandlerwertSIG_DFL
repräsentiert das Standardverhalten des Systems :quelle
Ein "Broken Pipe" -Fehler tritt auf, wenn Sie versuchen, in eine Pipe zu schreiben, die am anderen Ende geschlossen wurde. Da der von Ihnen gezeigte Code keine Pipes direkt enthält, vermute ich, dass Sie etwas außerhalb von Python tun, um die Standardausgabe des Python-Interpreters an eine andere Stelle umzuleiten. Dies kann passieren, wenn Sie ein Skript wie das folgende ausführen:
Das Problem, das Sie haben,
someothercommand
ist das Beenden, ohne alles zu lesen, was auf der Standardeingabe verfügbar ist. Dies führt dazu, dass Ihr Schreibvorgang (viaprint
) irgendwann fehlschlägt.Ich konnte den Fehler mit dem folgenden Befehl auf einem Linux-System reproduzieren:
Wenn ich den
less
Pager schließe, ohne durch alle Eingaben (1000 Zeilen) zu scrollen, wird Python mit dem vonIOError
Ihnen gemeldeten beendet.quelle
SIGPIPE
Signal zeigt nicht notwendigerweise eine Fehlerbedingung, einige Unix - Werkzeuge, vor allemhead
, durch Design, während der normalen Betriebes der Nähe des Rohr früh, sobald sie so viele Daten gelesen haben, wie sie brauchten.Ich fühle mich verpflichtet darauf hinzuweisen, dass die Methode verwendet
ist in der Tat gefährlich (wie bereits von David Bennet in den Kommentaren vorgeschlagen) und führte in meinem Fall in Kombination mit plattformabhängigen lustigen Geschäften
multiprocessing.Manager
(da die Standardbibliothek darauf beruht, dass BrokenPipeError an mehreren Stellen ausgelöst wird). Um es kurz und schmerzhaft zu machen: So habe ich es behoben:Zuerst müssen Sie
IOError
(Python 2) oderBrokenPipeError
(Python 3) fangen . Abhängig von Ihrem Programm können Sie versuchen, an diesem Punkt vorzeitig zu beenden oder die Ausnahme einfach zu ignorieren:Dies ist jedoch nicht genug. Python 3 druckt möglicherweise immer noch eine Nachricht wie folgt:
Leider ist es nicht einfach, diese Nachricht loszuwerden, aber ich habe schließlich http://bugs.python.org/issue11380 gefunden, wo Robert Collins diese Problemumgehung vorschlägt, mit der ich mich in einen Dekorateur verwandelt habe, mit dem Sie Ihre Hauptfunktion abschließen können (ja, das ist verrückt Vertiefung):
quelle
Ich weiß, dass dies nicht der "richtige" Weg ist, aber wenn Sie einfach daran interessiert sind, die Fehlermeldung zu beseitigen, können Sie diese Problemumgehung versuchen:
quelle
Dies kann auch auftreten, wenn das Leseende der Ausgabe Ihres Skripts vorzeitig beendet wird
dh open.py | otherCommand
Wenn otherCommand beendet wird und open.py versucht, in stdout zu schreiben
Ich hatte ein schlechtes Gawk-Skript, das mir das sehr angetan hat.
quelle
head
, durch Design, während der normalen Betriebes der Nähe des Rohr früh, nachdem sie so viele Daten gelesen hat , wie sie benötigt werden . Die meisten CLIs schieben das System einfach auf sein Standardverhalten zurück: Sie beenden den Lesevorgang leise und melden den Exit-Code141
(was in einer Shell nicht ohne weiteres ersichtlich ist, da der letzte Befehl einer Pipeline den gesamten Exit-Code bestimmt). Pythons Standardverhalten ist leider, laut zu sterben .Die Top-Antwort (
if e.errno == errno.EPIPE:
) hier hat bei mir nicht wirklich funktioniert. Ich habe:Dies sollte jedoch funktionieren, wenn Sie nur defekte Pipes bei bestimmten Schreibvorgängen ignorieren. Ich denke, es ist sicherer als SIGPIPE zu fangen:
Sie müssen natürlich eine Entscheidung treffen, ob Ihr Code wirklich, wirklich fertig ist, wenn Sie auf die kaputte Pipe treffen, aber für die meisten Zwecke denke ich, dass dies normalerweise der Fall sein wird. (Vergessen Sie nicht, Dateihandles usw. zu schließen.)
quelle
Das Schließen sollte in umgekehrter Reihenfolge wie das Öffnen erfolgen.
quelle