AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 565744
Accepted
joelostblom
joelostblom
Asked: 2020-02-05 07:47:17 +0800 CST2020-02-05 07:47:17 +0800 CST 2020-02-05 07:47:17 +0800 CST

为什么“BrokenPipeError”取决于管道流的大小?

  • 772

以下脚本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。

pipe python
  • 1 1 个回答
  • 3595 Views

1 个回答

  • Voted
  1. Best Answer
    pizdelect
    2020-02-05T08:59:14+08:002020-02-05T08:59:14+08:00

    为什么发生BrokenPipeError 取决于管道的大小?

    因为写更多的东西需要更多的时间,而且在你的 python 写完它之前,管道的右侧可能会死掉。此外,如果 python 尝试写入的内容超出管道缓冲区的容量,它将阻塞并提供head -1充足的退出时间。

    由于head -1需要一些时间来生存和死亡,python 可能会使用这段时间来编写它所有的东西——如果它适合管道缓冲区——并成功退出。这很难预测,因为内核可以自由地以任何顺序调度管道的两端,并且可能会延迟启动它head -1,只要它认为合适,或者它可能随时停止它。

    >>> python3 -c 'for i in range(50000): print("")' | sleep .01
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    BrokenPipeError: [Errno 32] Broken pipe
    
    >>> python3 -c 'for i in range(50000): print("")' | sleep .1
    
    # OK!
    

    但是如果 python 试图写的东西比它在管道中的容量多,它最终会不可避免地得到一个EPIPEor SIGPIPE,不管它有多少时间:

    >>> python3 -c 'for i in range(100000): print("")' | sleep 20
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    BrokenPipeError: [Errno 32] Broken pipe
    

    但这对我来说是 64K ......所以这似乎不是原因。

    请记住,当输出不是终端时,python 正在使用完全缓冲;它不是逐行或逐字节写入,而是按一定大小的块写入:

    >>> strace -s3 -e trace=write python3 -c 'for i in range(50000): print("")' | sleep .3
    write(1, "\n\n\n"..., 8193)             = 8193
    write(1, "\n\n\n"..., 8193)             = 8193
    write(1, "\n\n\n"..., 8193)             = 8193
    write(1, "\n\n\n"..., 8193)             = 8193
    write(1, "\n\n\n"..., 8193)             = 8193
    write(1, "\n\n\n"..., 8193)             = 8193
    write(1, "\n\n\n"..., 842)              = 842
    +++ exited with 0 +++
    
    • 3

相关问题

  • 列表理解中集合的 Python add() 函数

  • 如何在 unix 中获取应用程序的默认版本

  • 如何通过管道传输 bash 命令并保持 Ctrl+C 正常工作?

  • 为什么管道`mysql`到'tail'会改变输出格式?

  • `tee` 和 `bash` 进程替换顺序

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve