以下脚本BrokenPipeError: [Errno 32] Broken pipe
在通过管道传递到类似命令时会引发head
(除非要开头的行数超过 Python 脚本打印的行数)。
for i in range(16386):
print("")
$ python test-pipe.py | head -1
Traceback (most recent call last):
File "test-pipe.py", line 2, in <module>
print("")
BrokenPipeError: [Errno 32] Broken pipe
我的理解(从这个答案和这个问题的答案)是,如果在 Python 进程完成写入之前关闭管道,则会引发错误。
但是,如果我将迭代范围从 1 减少到 16385,则不会引发错误(不确定此阈值在所有机器上是否相同,因此可能只需尝试一个高低数字来重现)。我最初认为这可能与管道缓冲区大小有关,但对我来说是 64K(根据M=0; while printf A; do >&2 printf "\r$((++M)) B"; done | sleep 999
,所以这似乎不是原因。
为什么发生BrokenPipeError
取决于管道的大小?
这适用于 Linux 5.4.15-arch1-1 上的 Python 3.8.1。
因为写更多的东西需要更多的时间,而且在你的 python 写完它之前,管道的右侧可能会死掉。此外,如果 python 尝试写入的内容超出管道缓冲区的容量,它将阻塞并提供
head -1
充足的退出时间。由于
head -1
需要一些时间来生存和死亡,python 可能会使用这段时间来编写它所有的东西——如果它适合管道缓冲区——并成功退出。这很难预测,因为内核可以自由地以任何顺序调度管道的两端,并且可能会延迟启动它head -1
,只要它认为合适,或者它可能随时停止它。但是如果 python 试图写的东西比它在管道中的容量多,它最终会不可避免地得到一个
EPIPE
orSIGPIPE
,不管它有多少时间:请记住,当输出不是终端时,python 正在使用完全缓冲;它不是逐行或逐字节写入,而是按一定大小的块写入: