'是'报告错误与子进程通信() [英] 'yes' reporting error with subprocess communicate()

查看:16
本文介绍了'是'报告错误与子进程通信()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下函数在 Python 中运行命令:

I am using the following function to run a command in Python:

def run_proc(cmd):
    child = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = child.communicate()
    returncode = child.returncode
    return stdout, stderr, returncode

它一直运行良好,但是现在我正在尝试使用 yes 程序将输出通过管道传输到标准输入.我尝试运行的命令如下:

It has always been working fine, however now I'm trying to use the yes program to pipe output to stdin. The command I'm trying to run is the following:

yes '' | apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade

但我相信它可以用一个通用示例代替,例如:

but I believe it could be substituted with a general example, like:

yes | head -3 | cat

我的问题是,如果我尝试运行任何包含 yes | 的命令,上面的 subprocess.Popen 将包含错误消息:

My problem is that if I try to run any command which has yes | in it, the above subprocess.Popen will contain the error messages:

yes: standard output: Broken pipe
yes: write error

对我来说,管道似乎仍然有效,从 yes | 可以看出.头-3 |cat 的回答:y y y.

For me it seems that the piping still works, as can be seen from yes | head -3 | cat's answer: y y y.

我有以下问题:

  1. 即使 yes 报告错误,yes 管道是否仍然有效?
  2. 我该如何解决?

推荐答案

问题是 subprocess 模块 在 Python 3.2+ 之前不会将 SIGPIPE 信号处理程序恢复为默认操作.这就是为什么您会得到 EPIPE 写入错误.

The issue is that subprocess module before Python 3.2+ doesn't restore SIGPIPE signal handler to default action. That is why you get EPIPE write error instead.

在 Python 3.2+ 中

In Python 3.2+

>>> from subprocess import check_output
>>> check_output("yes | head -3", shell=True)
b'y
y
y
'

yeshead 退出时被 SIGPIPE 杀死.

yes is killed by SIGPIPE when head exits.

在 Python 2 中:

In Python 2:

>>> from subprocess import check_output
>>> check_output("yes | head -3", shell=True)
yes: standard output: Broken pipe
yes: write error
'y
y
y
'

yes 得到 EPIPE 写入错误.忽略该错误是安全的.它传达与 SIGPIPE 相同的信息.

yes got EPIPE write error. It is safe to ignore the error. It communicates the same information as SIGPIPE.

要解决此问题,您可以使用 preexec_fn 参数在 Python 2 中模拟 restore_signals :

To workaround the problem, you could emulate restore_signals in Python 2 using preexec_fn parameter :

>>> from subprocess import check_output
>>> import signal
>>> def restore_signals(): # from http://hg.python.org/cpython/rev/768722b2ae0a/
...     signals = ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ')
...     for sig in signals:
...         if hasattr(signal, sig):
...            signal.signal(getattr(signal, sig), signal.SIG_DFL)
... 
>>> check_output("yes | head -3", shell=True, preexec_fn=restore_signals)
'y
y
y
'

这篇关于'是'报告错误与子进程通信()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆