'yes' 报告子进程通信错误() [英] 'yes' reporting error with subprocess communicate()
问题描述
我正在使用以下函数在 Python 中运行命令:
def run_proc(cmd):child = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)标准输出,标准错误 = child.communicate()returncode = child.returncode返回标准输出、标准错误、返回码
它一直工作正常,但是现在我正在尝试使用 yes
程序将输出通过管道传输到标准输入.我试图运行的命令如下:
是 '' |apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
但我相信它可以用一个通用的例子代替,比如:
是 |头-3 |猫
我的问题是,如果我尝试运行任何包含 yes |
的命令,上面的 subprocess.Popen 将包含错误消息:
yes: 标准输出:断管是:写错误
对我来说,管道似乎仍然有效,从 yes | 可以看出头-3 |cat
的回答:y y y
.
我有以下问题:
- 即使 yes 报告错误,yes 管道是否仍然有效?
- 我该如何解决?
问题在于 subprocess
模块 在 Python 3.2+ 不将 SIGPIPE
信号处理程序恢复到默认操作之前.这就是为什么您会收到 EPIPE
写入错误的原因.
在 Python 3.2+ 中
<预><代码>>>>从子进程导入 check_output>>>check_output("yes | head -3", shell=True)b'y y y 'yes
在 head
退出时被 SIGPIPE
杀死.
在 Python 2 中:
<预><代码>>>>从子进程导入 check_output>>>check_output("yes | head -3", shell=True)是:标准输出:断管是:写错误'y y y 'yes
得到 EPIPE
写入错误.忽略错误是安全的.它传达与 SIGPIPE
相同的信息.
要解决此问题,您可以使用 preexec_fn
参数在 Python 2 中模拟 restore_signals
:
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
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
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
For me it seems that the piping still works, as can be seen from yes | head -3 | cat
's answer: y y y
.
I have the following questions:
- Is the yes piping still functional, even though yes reports error?
- How can I fix it?
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.
In Python 3.2+
>>> from subprocess import check_output
>>> check_output("yes | head -3", shell=True)
b'y
y
y
'
yes
is killed by SIGPIPE
when head
exits.
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
got EPIPE
write error. It is safe to ignore the error. It communicates the same information as SIGPIPE
.
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
'
这篇关于'yes' 报告子进程通信错误()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!