为什么在python2.7中使用subprocess.check_output(shell = true)会导致挂起?
代码
b.py中的
# b.py
import subprocess
from sys import stdout
cmd = ['python2.7','a.py']
try:
subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as e:
print 'cmd:', e.cmd, 'end'
print 'output:', e.output,'end'
print 'returncode:', e.returncode, 'end'
print 'ok'
在a.py中
# a.py
import sys
print 'a.py'
sys.stderr.write('stderr\n')
sys.stdout.write('stdout\n')
exit(-1)
,我
称呼python2.7 b.py
,它停止了,就好像在等待输入一样。
我键入ctrl-c
后,追溯是:
/home/liweiming/app/test〉python2.7 b.py 06/07/2022 11:25:07 AM
^CTraceback (most recent call last):
File "b.py", line 10, in <module>
subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
File "/usr/lib/python2.7/subprocess.py", line 217, in check_output
output, unused_err = process.communicate()
File "/usr/lib/python2.7/subprocess.py", line 475, in communicate
stdout = _eintr_retry_call(self.stdout.read)
File "/usr/lib/python2.7/subprocess.py", line 125, in _eintr_retry_call
return func(*args)
KeyboardInterrupt
但是,如果我使用subprocess.check_output(shell = false)
,则该程序很好。
Code
in b.py
# b.py
import subprocess
from sys import stdout
cmd = ['python2.7','a.py']
try:
subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as e:
print 'cmd:', e.cmd, 'end'
print 'output:', e.output,'end'
print 'returncode:', e.returncode, 'end'
print 'ok'
in a.py
# a.py
import sys
print 'a.py'
sys.stderr.write('stderr\n')
sys.stdout.write('stdout\n')
exit(-1)
What I do
after I call python2.7 b.py
, it stopped, as if waiting for input.
after I type ctrl-c
, the traceback is:
/home/liweiming/app/test〉python2.7 b.py 06/07/2022 11:25:07 AM
^CTraceback (most recent call last):
File "b.py", line 10, in <module>
subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
File "/usr/lib/python2.7/subprocess.py", line 217, in check_output
output, unused_err = process.communicate()
File "/usr/lib/python2.7/subprocess.py", line 475, in communicate
stdout = _eintr_retry_call(self.stdout.read)
File "/usr/lib/python2.7/subprocess.py", line 125, in _eintr_retry_call
return func(*args)
KeyboardInterrupt
But if I use subprocess.check_output(shell=False)
, the program is well.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用
shell = true
命令变为['sh','-c','python2.7','a.py']
- 此通过a.py
作为sh
的参数(大致忽略了 - 在交互式脚本中将其设置为$ 0
,但这没关系,因为该脚本只是python2.7
) - 然后运行python2.7
,因为该命令仍将其附加到终端上,因此它将等待输入(就像交互式解释器一样) - 例如,尝试键入
1 + 1&lt; enter&gt;&lt;^d&gt;
,并且您将获得输出(从Interactivepython2.7
本身)绝对是一个怪异的行为,我宁愿希望命令为列表 + shell = true会引起typeError(要求命令是字符串) - 但可惜
以下是
shell = true
行为的示例将位置参数传递给外壳字符串:with
shell=True
the command becomes['sh', '-c', 'python2.7', 'a.py']
-- this passesa.py
as an argument tosh
(which is roughly ignored -- it's set as$0
in the interactive script but it doesn't matter because that script is justpython2.7
) -- this then runspython2.7
since that command is still attached to the terminal, it will wait for input (as the interactive interpreter does) -- try for instance typing
1 + 1<enter><^D>
and you'll get output back (from the interactivepython2.7
itself)definitely a weird behaviour, I would've rather hoped that command being a list + shell=True would raise a TypeError (requiring the command to be a string) -- but alas
here's an example of the
shell=True
behaviour passing positional arguments to the shell string: