我觉得有必要指出
signal(SIGPIPE, SIG_DFL)
确实是很危险的(正如David Bennet在评论中所建议的那样),并且在我的案例中,与之结合使用时会导致依赖平台的滑稽生意multiprocessing.Manager
(因为标准库依赖在多个地方引发BrokenPipeError)。为了使一个长而痛苦的故事简短,我将其固定为:
首先,您需要捕获IOError
(Python 2)或BrokenPipeError
(Python 3)。根据您的程序,您可以尝试在此时提前退出或忽略该异常:
from errno import EPIPE
try:
broken_pipe_exception = BrokenPipeError
except NameError:
broken_pipe_exception = IOError
try:
YOUR CODE GOES HERE
except broken_pipe_exception as exc:
if broken_pipe_exception == IOError:
if exc.errno != EPIPE:
raise
但是,这还不够。Python 3可能仍会打印如下消息:
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe
不幸的是,摆脱该消息并不是一件容易的事,但是我终于找到了http://bugs.python.org/issue11380,Robert Collins提出了这种解决方法,我把它变成了一个装饰器,您可以使用它包装主函数(是的,这有点疯狂缩进):
from functools import wraps
from sys import exit, stderr, stdout
from traceback import print_exc
def suppress_broken_pipe_msg(f):
@wraps(f)
def wrapper(*args, **kwargs):
try:
return f(*args, **kwargs)
except SystemExit:
raise
except:
print_exc()
exit(1)
finally:
try:
stdout.flush()
finally:
try:
stdout.close()
finally:
try:
stderr.flush()
finally:
stderr.close()
return wrapper
@suppress_broken_pipe_msg
def main():
YOUR CODE GOES HERE
print(f1.readlines())