2013-04-03 8 views
8

Ich versuche, eine Liste von Tupeln zu drucken, die in meinem stdout formatiert sind. Dazu verwende ich die str.format Methode. Alles funktioniert gut, aber wenn ich die Ausgabe übergebe, um die ersten Zeilen zu sehen, die den head Befehl verwenden, tritt ein IOError auf.Wie vermeide ich einen Broken Pipe-Fehler beim Drucken einer großen Menge formatierter Daten?

Hier ist mein Code:

# creating the data 
data = []$ 
for i in range(0, 1000):            
    pid = 'pid%d' % i 
    uid = 'uid%d' % i 
    pname = 'pname%d' % i 
    data.append((pid, uid, pname)) 

# find max leghed string for each field 
pids, uids, pnames = zip(*data) 
max_pid = len("%s" % max(pids)) 
max_uid = len("%s" % max(uids)) 
max_pname = len("%s" % max(pnames)) 

# my template for the formatted strings 
template = "{0:%d}\t{1:%d}\t{2:%d}" % (max_pid, max_uid, max_pname) 

# print the formatted output to stdout 
for pid, uid, pname in data: 
    print template.format(pid, uid, pname) 

Und hier ist der Fehler, den ich nach dem Ausführen des Befehls erhalten: python myscript.py | head

Traceback (most recent call last): 
    File "lala.py", line 16, in <module> 
    print template.format(pid, uid, pname) 
IOError: [Errno 32] Broken pipe 

jemand mir auf diesem helfen?

ich versuchte print in einem try-except Block zu setzen, den Fehler zu umgehen, aber nach, dass es eine andere Nachricht in der Konsole:

close failed in file object destructor: 
sys.excepthook is missing 
lost sys.stderr 

I auch versucht, die Daten sofort durch ein zwei aufeinander folgenden zu spülen happend sys.stdout.write und sys.stdout.flush Anrufe, aber nichts ..

+2

Dies geschieht, weil 'head' * schließt *' stdout', wodurch 'print' versucht, in eine geschlossene Datei zu schreiben. Was möchten Sie stattdessen tun? –

+0

Ok, danke! Ich möchte das Drucken solcher Nachrichten in der Konsole vermeiden. Ich möchte eine Variante dieses Codes für ein Befehlszeilentool verwenden. –

+1

Diese Frage ist ein mögliches Duplikat; siehe: http://stackoverflow.com/questions/11423225/why-does-my-python3-script-balk-at-piping-its-output-to-head-o-tail-sys-module –

Antwort

10

head von stdout liest dann schließt es. Dies führt dazu, dass print fehlschlägt, intern schreibt es in sys.stdout, jetzt geschlossen.

Sie können einfach fangen die IOError und Ausfahrt still:

try: 
    for pid, uid, pname in data: 
     print template.format(pid, uid, pname) 
except IOError: 
    # stdout is closed, no point in continuing 
    # Attempt to close them explicitly to prevent cleanup problems: 
    try: 
     sys.stdout.close() 
    except IOError: 
     pass 
    try: 
     sys.stderr.close() 
    except IOError: 
     pass 
+0

ok in diesem einfachen Programm dies funktioniert, aber in der Befehlszeile Werkzeug manchmal funktioniert und manchmal wieder diese Meldung auftritt: 'Schließen fehlgeschlagen in Datei Objektdestruktor: sys.excepthook fehlt verloren sys.stderr' –

+0

@ThanasisPetsas: Eine Lösung gefunden für das auch. –

+0

Haha! Ich habe es auch in einer Antwort bei stackoverflow gefunden! Ich habe es versucht, aber es funktioniert nicht! Es scheint, dass es eine Race-Bedingung gibt .. Aber ich kann nicht herausfinden, wie man es löst. –

1

Das Verhalten, das Sie an die gepufferte Ausgang Implementierung in Python3 verbunden sind, zu sehen. Das Problem kann vermieden werden, indem die Option -u verwendet wird oder die Umgebungsvariable PYTHONUNBUFFERED = x gesetzt wird. Weitere Informationen zu -u finden Sie auf den man-Seiten.

$ python2.7 testprint.py | echo 

Exc: <type 'exceptions.IOError'> 
$ python3.5 testprint.py | echo 

Exc: <class 'BrokenPipeError'> 
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> 
BrokenPipeError: [Errno 32] Broken pipe 
$ python3.5 -u testprint.py | echo 

Exc: <class 'BrokenPipeError'> 
$ export PYTHONUNBUFFERED=x 
$ python3.5 testprint.py | echo 

Exc: <class 'BrokenPipeError'> 
+0

Yup, aber ich hatte dieses Problem in Python2.7. Ich benutze Python3 nicht. –

0

Im Allgemeinen versuche ich, den spezifischsten Fehler zu finden, mit dem ich durchkommen kann. In diesem Fall ist es BrokenPipeError:

try: 
    # I usually call a function here that generates all my output: 
    for pid, uid, pname in data: 
     print template.format(pid, uid, pname) 
except BrokenPipeError as e: 
    pass # Ignore. Something like head is truncating output. 
finally: 
    sys.stderr.close() 

Wenn dies am Ende der Ausführung ist, finde ich, ich brauche nur sys.stderr zu schließen. Wenn ich nicht sys.stderr schließe, erhalte ich einen BrokenPipeError aber ohne einen Stack-Trace.

Dies scheint der minimale Fix für Schreibwerkzeuge zu sein, die in Pipelines ausgegeben werden.

1

Hatte dieses Problem mit Python3 und Debug-Logging Pipe in Kopf. Wenn Ihr Skript mit dem Netzwerk kommuniziert oder eine Datei-IO ausführt, ist das einfache Löschen von IOError keine gute Lösung. Trotz Erwähnungen hier konnte ich BrokenPipeError aus irgendeinem Grund nicht fangen.

einen Blogeintrag gefunden sprechen über die Standard-Signal-Handler für SIGPIPE Wiederherstellung:

if log.isEnabledFor(logging.DEBUG): # optional 
    # set default handler to no-op 
    from signal import signal, SIGPIPE, SIG_DFL 
    signal(SIGPIPE, SIG_DFL) 

Dies scheint: http://newbebweb.blogspot.com/2012/02/python-head-ioerror-errno-32-broken.html

Kurz gesagt, Sie folgendes Skript vor der Masse des Ausgangs hinzufügen passieren mit Kopf, aber nicht andere Programme wie Grep --- wie erwähnt, Kopf schließt stdout. Wenn Sie nicht oft mit dem Skript arbeiten, ist es vielleicht nicht wichtig, sich darüber Gedanken zu machen.

+1

Großartig! Danke für die Erklärung und den Artikel! –

Verwandte Themen