【问题标题】:"OSError: [Errno 22] Invalid argument" on Windows with print() and output piped“OSError:[Errno 22] Invalid argument”在 Windows 上使用 print() 和输出管道
【发布时间】:2015-12-09 21:20:25
【问题描述】:

当使用无效参数将 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
  • 指挥官
  • msysgit 2.5.1.windows.1

【问题讨论】:

  • @achampion 对,它没有选项。这就是Python中发生错误的原因。我想知道这个OSError 到底发生了什么,以及为什么它与传递给wc 的无效参数有关。
  • wc 在看到关闭管道的无效选项时退出,python 继续写入管道并失败。幸运的是,对于同一异常 (Mac OSX),我收到了更合理的错误消息:BrokenPipeError: [Errno 32] Broken pipe
  • 不要把EINVAL的意义放在股票上。 CRT 必须将数千个 Win32 错误代码映射到大约 40 个errno 值。这里的 Win32 错误可能是ERROR_NO_DATA,因为管道正在关闭。原则上我认为这应该映射到EPIPE(断管),但由于某种原因,CRT 使用默认值EINVAL(无效参数)。

标签: python windows msysgit wc


【解决方案1】:

作为@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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-26
    • 2020-04-07
    • 2018-12-02
    • 1970-01-01
    • 2020-07-29
    • 2019-06-29
    • 2018-06-15
    • 1970-01-01
    相关资源
    最近更新 更多