“是”报告错误与subprocess通信()

我正在使用以下函数在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程序来pipe道输出到标准input。 我试图运行的命令如下:

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

但我相信它可以用一个一般的例子来代替,例如:

 yes | head -3 | cat 

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

 yes: standard output: Broken pipe yes: write error 

对我来说,似乎pipe道仍然有效,从yes | head -3 | cat可以看出 yes | head -3 | cat yes | head -3 | cat的回答: yyy

我有以下问题:

  1. 是pipe道仍然function,即使是报告错误?
  2. 我该如何解决?

Solutions Collecting From Web of "“是”报告错误与subprocess通信()"

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

在Python 3.2+

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

head退出时被SIGPIPE杀死。

在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得到了EPIPE写入错误。 忽略错误是安全的。 它传达与SIGPIPE相同的信息 。

要解决这个问题,可以使用preexec_fn参数在Python 2中模拟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: ... 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' 

另一个问题的答案为什么…我会尽力给你一个解决办法

你能不能做点什么吗?

 proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin = subprocess.PIPE) for i in range(10): #send 10 y's time.sleep(1) # 1 second apart proc.stdin.write("y") #you may also need to send a newline ... print proc.communicate() 

见下面(我没有打扰,因为头没有真的做很多)

 >>> import subprocess >>> proc = subprocess.Popen("head -3", ... shell = True, ... stdout = subprocess.PIPE, ... stderr=subprocess.PIPE, ... stdin=subprocess.PIPE) >>> for i in range(10): ... proc.stdin.write("y\n") ... >>> proc.communicate() ('y\ny\ny\n', '') 

他说:

 yes | head -3 

会导致head发送SIGPIPE到一旦完成读取3行输入,即它会发送一个信号终止yes

 $ yes | head -3 y y y $ echo "${PIPESTATUS[@]}" 141 0 

解决办法是避免SIGPIPE