Python print和带有无效参数的wc会导致OSError

时间:2015-09-13 22:38:18

标签: python windows msysgit wc

当使用无效参数将Python脚本的输出传递给wc时,我遇到了一些(对我而言)奇怪的行为。

λ 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
  • Cmder
  • msysgit 2.5.1.windows.1

1 个答案:

答案 0 :(得分:0)

作为 @AChampion noted,这是 IOError: [Errno 32] Broken pipe when piping: `prog.py | othercmd` 的 Windows 版本,并附加了一个警告,即 Python 无法引发正确的异常(即 BrokenPipeError)。

issue 35754 “[Windows] 损坏管道上的 I/O 可能会引发 EINVAL OSError 而不是 BrokenPipeError” Python 的错误跟踪器。

在修复之前,我没有看到处理它的通用方法。

How to duplicate sys.stdout to a log file? 有助于解决基于 Python 的输出(通过 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)