As @AChampion noted, this is the Windows version of IOError: [Errno 32] Broken pipe when piping: `prog.py | othercmd` with the added caveat that Python fails to raise the correct exception (i.e. BrokenPipeError
).
There's issue 35754 "[Windows] I/O on a broken pipe may raise an EINVAL OSError instead of BrokenPipeError" Python's bug tracker.
Until it's fixed, I don't see a general way to handle it.
How to duplicate sys.stdout to a log file? helps solve this for Python-based output (printing via sys.stdout
):
class IgnoreBrokenPipe(object):
def __init__(self, stream):
self.stream = stream
def ignore_einval(fn):
from functools import wraps
@wraps(fn)
def wrapper(*args, **kwargs):
try:
return fn(*args, **kwargs)
except OSError as exc:
if exc.errno != 22:
raise exc
else: # mimicking the default SIGPIPE behavior on Windows
sys.exit(1)
return wrapper
self.write = ignore_einval(lambda data: self.stream.write(data))
self.flush = ignore_einval(lambda: self.stream.flush())
import sys
sys.stdout = IgnoreBrokenPipe(sys.stdout)
OSError
is caused and why it has to do with an invalid argument passed towc
. – Perceivewc
is exiting when it sees an invalid option which closes the pipe, python continues to write to the pipe and fails. Fortunately, I get a more reasonable error message for the same exception (Mac OSX):BrokenPipeError: [Errno 32] Broken pipe
. – GrandmotherEINVAL
. The CRT has to map thousands of Win32 error codes to just about 40errno
values. Probably the Win32 error here isERROR_NO_DATA
because the pipe is being closed. In principle I think this should map toEPIPE
(broken pipe), but for some reason the CRT uses the default value ofEINVAL
(invalid argument). – Calva