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

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

问题描述

我使用以下函数在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 程序将输出管道输出到stdin。我试图运行的命令如下:

  yes''| apt-get -y -o Dpkg :: Options :: = -  force-confdef-o Dpkg :: Options :: = -  force-confolddist-upgrade 



但我相信它可以替换为一般的例子,如:

  yes |头-3 |我的问题是,如果我尝试运行任何命令,是的,我的问题是,如果我尝试运行任何命令, | 在其中,上面的子进程.popen将包含错误消息:

  :破损的管道
是:写入错误

对我来说,管道似乎仍然工作,从 yes |中可以看出头-3 | cat 的回答: yyy



我有以下问题: p>


  1. 是管道仍然有效,即使是报告错误吗?

  2. 如何解决?


解决方案

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



在Python 3.2中

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

$当 head 时,由 SIGPIPE / code>退出。



在Python 2中:

 >>>> from subprocess import check_output 
>>>> check_output(yes | head -3,shell = True)
是:标准输出:管道损坏
是:写入错误
'y \\\
y\\\
y\\\
'

获得 EPIPE 写入错误。忽略错误是安全的。 它与 SIGPIPE 传递相同的信息。

$为了解决这个问题,你可以在Python 2中使用 preexec_fn 来模拟 restore_signals 参数:

 >>> 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:
...如果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\\\
'


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\ny\ny\n'

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\ny\ny\n'

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\ny\ny\n'

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

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