'是'报告错误与子进程通信() [英] 'yes' reporting error with subprocess communicate()
问题描述
我正在使用以下函数在 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
.
我有以下问题:
- 即使 yes 报告错误,yes 管道是否仍然有效?
- 我该如何解决?
推荐答案
问题是 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
'
yes
在 head
退出时被 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屋!