hyp*_*not 4 python linux shell command-line 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
Run Code Online (Sandbox Code Playgroud)
它一直工作正常,但现在我正在尝试使用该yes
程序将输出管道输出到stdin.我正在尝试运行的命令如下:
yes '' | apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
Run Code Online (Sandbox Code Playgroud)
但我相信它可以用一般的例子代替,例如:
yes | head -3 | cat
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果我尝试运行其中的任何命令yes |
,上面的subprocess.Popen将包含错误消息:
yes: standard output: Broken pipe
yes: write error
Run Code Online (Sandbox Code Playgroud)
对我来说,似乎管道仍然可以工作,从yes | head -3 | cat
答案中可以看出:y y y
.
我有以下问题:
问题是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'
Run Code Online (Sandbox Code Playgroud)
yes
被退出SIGPIPE
时被杀死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'
Run Code Online (Sandbox Code Playgroud)
yes
写错了EPIPE
.忽略错误是安全的.它传达相同的信息SIGPIPE
.
要解决此问题,您可以restore_signals
使用preexec_fn
参数在Python 2中进行模拟:
>>> 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'
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2015 次 |
最近记录: |