Tôi cảm thấy có nghĩa vụ chỉ ra rằng phương pháp sử dụng
signal(SIGPIPE, SIG_DFL)
thực sự nguy hiểm (như đã được David Bennet đề xuất trong phần nhận xét) và trong trường hợp của tôi dẫn đến việc kinh doanh hài hước phụ thuộc vào nền tảng khi kết hợp vớimultiprocessing.Manager
(vì thư viện tiêu chuẩn dựa vào BrokenPipeError đang được nâng lên ở một số nơi). Để làm cho một câu chuyện dài và đau đớn trở nên ngắn gọn, đây là cách tôi sửa nó:
Trước tiên, bạn cần bắt IOError
(Python 2) hoặc BrokenPipeError
(Python 3). Tùy thuộc vào chương trình của bạn, bạn có thể cố gắng thoát sớm tại thời điểm đó hoặc chỉ bỏ qua ngoại lệ:
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
Tuy nhiên, điều này vẫn chưa đủ. Python 3 vẫn có thể in một thông báo như thế này:
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe
Thật không may, việc loại bỏ thông báo đó không đơn giản, nhưng cuối cùng tôi đã tìm thấy http://bugs.python.org/issue11380 nơi Robert Collins đề xuất giải pháp này mà tôi đã biến thành một người trang trí mà bạn có thể kết hợp chức năng chính của mình (vâng, đó là một điều điên rồ thụt đầu dòng):
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())