“OSError: [Errno 22] 无效参数";在带有 print() 和管道输出的 Windows 上
在将 Python 脚本的输出通过无效参数通过管道传输到 wc
时,我遇到了一些(对我而言)奇怪的行为.
I've come across some (to me) weird behaviour when piping the output of a Python script into wc
with invalid arguments.
λ python test.py
Hello!
λ python test.py | wc -li
wc: unknown option -- i
Try 'wc --help' for more information.
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='cp1252'>
OSError: [Errno 22] Invalid argument
这里发生了什么?
我的配置是
- Windows 10
- 指挥官
- msysgit 2.5.1.windows.1
As @AChampion 指出,这是 IOError:[Errno 32] 管道破裂:`prog.py |othercmd` 并添加了一个警告,即 Python 无法引发正确的异常(即 BrokenPipeError
).
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
).
问题 35754 "[Windows] I/O 可能在损坏的管道上引发 EINVAL OSError 而不是 BrokenPipeError Python 的错误跟踪器.
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.
如何将 sys.stdout 复制到日志文件? 有助于解决基于 Python 的输出(通过 sys.stdout):
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)