BrokenPipeError
является нормальным, как упомянутый фантом, потому что процесс чтения (голова) завершается и закрывает свой конец канала, в то время как процесс записи (python) все еще пытается писать.
является ненормальным состоянием, и скрипты Python получают BrokenPipeError
— точнее, интерпретатор Python получает системный сигнал SIGPIPE, который он перехватывает и поднимает BrokenPipeError
, чтобы скрипт мог обработать ошибку.
И вы эффективно можете обработать ошибку, потому что в вашем последнем примере вы видите только сообщение о том, что исключение было проигнорировано — хорошо, это неправда, но похоже, что это связано с этим открытая проблема в Python: разработчики Python считают важным предупредить пользователя о ненормальном состоянии.
Что на самом деле происходит, так это то, что интерпретатор python всегда сигнализирует об этом на stderr, даже если вы поймаете исключение. Но вам просто нужно закрыть stderr перед выходом, чтобы избавиться от сообщения.
Я немного изменил ваш скрипт на:
- поймать ошибку, как в последнем примере
- поймать либо IOError (которую я получаю в Python34 на Windows64), либо BrokenPipeError (в Python 33 на FreeBSD 9.0) — и отобразить сообщение для этого
- отображать пользовательское сообщение Done на стандартном потоке (stdout закрыт из-за поломки конвейера)
- закройте stderr перед выходом, чтобы избавиться от сообщения
Вот скрипт, который я использовал:
import sys
try:
for i in range(4000):
print(i, flush=True)
except (BrokenPipeError, IOError):
print ('BrokenPipeError caught', file = sys.stderr)
print ('Done', file=sys.stderr)
sys.stderr.close()
и вот результат python3.3 pipe.py | head -10
:
0
1
2
3
4
5
6
7
8
9
BrokenPipeError caught
Done
Если вы не хотите, чтобы посторонние сообщения просто использовали:
import sys
try:
for i in range(4000):
print(i, flush=True)
except (BrokenPipeError, IOError):
pass
sys.stderr.close()
person
Serge Ballesta
schedule
04.11.2014