ฉันรู้สึกว่าจำเป็นต้องชี้ให้เห็นว่าวิธีการใช้
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())