subprocess.Popen() 在Eclipse/PyCharm和终端执行中表现不一致
我遇到的问题是,Eclipse和PyCharm在处理subprocess的Popen()结果时,与标准终端的表现不一样。所有的环境都是在OSX上使用python2.6.1。
这里有一个简单的示例脚本:
import subprocess
args = ["/usr/bin/which", "git"]
print "Will execute %s" % " ".join(args)
try:
p = subprocess.Popen(["/usr/bin/which", "git"], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# tuple of StdOut, StdErr is the responses, so ..
ret = p.communicate()
if ret[0] == '' and ret[1] <> '':
msg = "cmd %s failed: %s" % (fullcmd, ret[1])
if fail_on_error:
raise NameError(msg)
except OSError, e:
print >>sys.stderr, "Execution failed:", e
在标准终端中,以下这一行:
ret = p.communicate()
给我的结果是:
(Pdb) print ret
('/usr/local/bin/git\n', '')
但是在Eclipse和PyCharm中,我得到的是一个空的元组:
ret = {tuple} ('','')
更改shell=的值也没有解决这个问题。在终端中,设置shell=True,并且把命令一起传入(也就是说,args=["/usr/bin/which git"])得到的结果是:ret = ('/usr/local/bin/git\n', '')。而Eclipse和PyCharm也都给我一个空的元组。
有没有人知道我可能哪里做错了?
1 个回答
15
好的,我找到了问题所在,这在使用Unix类型环境中的IDE时是个重要的事情。IDE的运行环境和你在终端里使用的环境是不同的(这很明显,对吧?)。我没有考虑到子进程使用的环境和我终端里的环境不同(我的终端设置了bash_profile,里面有更多的路径)。
这个问题可以通过如下修改脚本来轻松验证:
import subprocess
args = ["/usr/bin/which", "git"]
print "Current path is %s" % os.path.expandvars("$PATH")
try:
p = subprocess.Popen(args, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# tuple of StdOut, StdErr is the responses, so ..
out, err = p.communicate()
if err:
msg = "cmd %s failed: %s" % (fullcmd, err)
except OSError, e:
print >>sys.stderr, "Execution failed:", e
在终端中,路径包含/usr/local/bin,而在IDE中则不包含!
这对我来说是个重要的提醒——一定要记得环境的不同!