C'è un problema noto in Python, dove "close failed in file object destructor" when "Broken pipe" happens on stdout - Python tracker Issue 11380; visto anche in python - Why does my Python3 script balk at piping its output to head or tail (sys module)? - Stack Overflow.Soppressione stampa di "Exception ... ignorato" messaggio in Python 3
Quello che voglio fare, è stampato lo stesso messaggio personalizzato quando questo problema si verifica, sia in Python 2.7 e Python 3+. Così mi preparo uno script di test, testprint.py
ed eseguirlo (frammenti mostrati fatto in bash
, Ubuntu 11.04):
$ cat > testprint.py <<"EOF"
import sys
def main():
teststr = "Hello " * 5
sys.stdout.write(teststr + "\n")
if __name__ == "__main__":
main()
EOF
$ python2.7 testprint.py
Hello Hello Hello Hello Hello
$ python2.7 testprint.py | echo
close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr
$ python3.2 testprint.py | echo
Exception IOError: (32, 'Broken pipe') in <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> ignored
Come previsto dal link sopra, ci sono due messaggi differenti. In Help with a piping error (velocityreviews.com), si raccomanda di utilizzare sys.stdout.flush()
per forzare Python 2 per registrare un IOError invece di quel messaggio; con questo, abbiamo:
$ cat > testprint.py <<"EOF"
import sys
def main():
teststr = "Hello " * 5
sys.stdout.write(teststr + "\n")
sys.stdout.flush()
if __name__ == "__main__":
main()
EOF
$ python2.7 testprint.py | echo
Traceback (most recent call last):
File "testprint.py", line 9, in <module>
main()
File "testprint.py", line 6, in main
sys.stdout.flush()
IOError: [Errno 32] Broken pipe
$ python3.2 testprint.py | echo
Traceback (most recent call last):
File "testprint.py", line 9, in <module>
main()
File "testprint.py", line 6, in main
sys.stdout.flush()
IOError: [Errno 32] Broken pipe
Exception IOError: (32, 'Broken pipe') in <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> ignored
OK, sempre più vicino ... Ora, il modo di "ignora" queste eccezioni (o nel mio caso, sostituirlo con un messaggio di errore personalizzato), è quello di gestirli:
Ignore exceptions - comp.lang.python
> c'è un modo per rendere [interprete] ignorare le eccezioni.
No. Gestisci le eccezioni o scrivi codice che non genera eccezioni.
... e come An Introduction to Python - Handling Exceptions note, il modo per farlo è un try/except block. Quindi proviamo che:
$ cat > testprint.py <<"EOF"
import sys
def main():
teststr = "Hello " * 5
try:
sys.stdout.write(teststr + "\n")
sys.stdout.flush()
except IOError:
sys.stderr.write("Exc: " + str(sys.exc_info()[0]) + "\n")
if __name__ == "__main__":
main()
EOF
$ python2.7 testprint.py | echo
Exc: <type 'exceptions.IOError'>
$ python3.2 testprint.py | echo
Exc: <class 'IOError'>
Exception IOError: (32, 'Broken pipe') in <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> ignored
Ok, quindi cercate/ad eccezione delle opere come mi aspetto che per Python 2.7 - ma poi, Python 3.2 entrambe le maniglie come previsto, ed ancora genera un messaggio Exception ... ignored
! Qual è il problema - non è "except IOError
" sufficiente per Python 3? Ma deve essere - altrimenti non avrebbe stampato il messaggio "Exc:...
" personalizzato!
Quindi, qual è il problema qui e perché lo Exception ... ignored
è ancora stampato in Python 3, anche se gestisco l'eccezione? E ancora più importante, come faccio a gestire in modo che il Exception ... ignored
fa non ottenere più stampate?
Funziona per me con la testa, la coda, meno, più e unico, quindi sembra che ci sia un bug reale nell'interazione con l'eco in particolare. La parte "Eccezione ignorata" sta effettivamente accadendo durante lo spegnimento dell'interprete quando tenta di scaricare nuovamente i flussi standard. – ncoghlan