subprocess.Popen () имеет противоречивое поведение между Eclipse / PyCharm и выполнением терминала - PullRequest
8 голосов
/ 11 августа 2010

Проблема, с которой я столкнулся, заключается в том, что Eclipse / PyCharm интерпретирует результаты Popen () подпроцесса не так, как стандартный терминал.Все используют python2.6.1 в OSX.

Вот простой пример сценария:

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 Ответ

14 голосов
/ 13 августа 2010

Хорошо, обнаружил проблему, и это важно помнить при использовании IDE в среде Unix-типа. IDE работают в ином контексте среды, чем пользователь терминала (да, верно ?!). Я не думал, что подпроцесс использует другую среду, отличную от той, которая у меня есть для моего терминала (в моем терминале установлено bash_profile, чтобы иметь больше объектов в PATH).

Это легко проверить, изменив скрипт следующим образом:

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 это не так!

Это важный вопрос для меня - всегда помни об окружающей среде!

...