我正在使用以下函数在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
yes '' | apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
但我相信可以用一般示例代替它,例如:
yes | head -3 | cat
我的问题是,如果我尝试运行其中包含的任何命令yes |,则上面的subprocess.Popen将包含错误消息:
yes |
yes: standard output: Broken pipe yes: write error
对我来说,管道似乎仍然有效,从yes | head -3 | cat的答案可以看出:y y y。
y y y
我有以下问题:
问题在于,Python 3.2+之前的subprocess模块无法将SIGPIPE信号处理程序恢复为默认操作。这就是为什么您会收到EPIPE写入错误的原因。
subprocess
SIGPIPE
EPIPE
在Python 3.2+中
>>> from subprocess import check_output >>> check_output("yes | head -3", shell=True) b'y\ny\ny\n'
yes退出SIGPIPE时被杀死head。
head
在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写错误。可以忽略该错误
要解决该问题,您可以restore_signals使用preexec_fn参数在Python 2中进行仿真:
restore_signals
preexec_fn
>>> 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'