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

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

问题描述

我正在使用以下函数在 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.

我有以下问题:

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

解决方案

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

在 Python 3.2+ 中

<预><代码>>>>从子进程导入 check_output>>>check_output("yes | head -3", shell=True)b'y y y '

yeshead 退出时被 SIGPIPE 杀死.

在 Python 2 中:

<预><代码>>>>从子进程导入 check_output>>>check_output("yes | head -3", shell=True)是:标准输出:断管是:写错误'y y y '

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

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

<预><代码>>>>从子进程导入 check_output>>>输入信号>>>def restore_signals(): # 来自 http://hg.python.org/cpython/rev/768722b2ae0a/... 信号 = ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ')...用于登录信号:...如果 hasattr(signal, sig):...信号.信号(getattr(信号,信号),信号.SIG_DFL)...>>>check_output("yes | head -3", shell=True, preexec_fn=restore_signals)'y y y '

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:

  1. Is the yes piping still functional, even though yes reports error?
  2. 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屋!

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