Python:subprocess.call 破管

标签 python bash subprocess

我试图在 python 中调用一个 shell 脚本,但它一直报告 broken pipe 错误(结果没问题,但我不想在 STDERR 中看到错误消息)。我已经查明了原因,它可以重现为以下片段:

subprocess.call('cat/dev/zero | head -c 10 | base64', shell=True)

AAAAAAAAAAAAAAAA==

猫:写入错误:管道损坏

/dev/zero 是一个无限流,但是 head -c 10 只从中读取 10 个字节就退出了,然后 cat 会因为 peer 而得到 SIGPIPE已关闭管道。在 shell 中运行命令时没有 broken pipe 错误消息,但为什么 python 显示它?

最佳答案

SIGPIPE 信号的默认操作是终止程序。 Python 解释器将其更改为 SIG_IGN,以便能够以异常的形式向程序报告损坏的管道错误。

当你在 shell 中执行 cat ... |head ... 时,cat 有默认的 SIGPIPE 处理程序,操作系统内核只是在 SIGPIPE 上终止它。

当您使用 subprocess 执行 cat 时,它会从其父进程(python 解释器)派生 SIGPIPE 处理程序,SIGPIPE 将被忽略,而 cat 会处理通过检查 errno 变量并打印错误消息来错误本身。

为了避免来自 cat 的错误消息,您可以使用 preexec_fn 参数给 subprocess.call:

from signal import signal, SIGPIPE, SIG_DFL
subprocess.call(
    'cat /dev/zero | head -c 10 | base64',
    shell = True,
    preexec_fn = lambda: signal(SIGPIPE, SIG_DFL)
)

关于Python:subprocess.call 破管,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10479825/

相关文章:

linux - Fedora bash 命令错误

python - bufsize must be an integer error while grepping a message

python - 如何使用 ([start ,] stop [, step]) 之类的签名实现 python 方法,即左侧的默认关键字参数

python - 哪个版本的 pygame 适合我?

linux - 如何使用 bash shell 处理目录中的文件

string - 解析字符串以查找可能引用的字段的通用 shell/bash 方法?

python - 如何停止将 SIGINT 传递给 python 中的子进程?

python - 如何从 Python 脚本执行 Cassandra CLI 命令?

Python lambda 函数在 elasticache 连接失败时超时

python - 将输入整数直接排序到列表中