Модуль подпроцесса не запускает команду - PullRequest
4 голосов
/ 25 октября 2011

Я пытаюсь выполнить cpplint.py от Google для группы моих файлов и собрать результаты в один файл журнала. Однако мне не удалось победить модуль подпроцесса. Мой текущий код здесь:

import os, subprocess

rootdir = "C:/users/me/Documents/dev/"
srcdir = "project/src/"

with open(rootdir+srcdir+"log.txt", mode='w', encoding='utf-8') as logfile:
    for subdir, dirs, files in os.walk(rootdir+srcdir):
        for file in files:
            if file.endswith(".h") or file.endswith(".cpp"):
                filewithpath=os.path.join(subdir, file)
                cmd=['c:/Python27/python.exe','C:/users/me/Documents/dev/cpplint.py','--filter=-whitespace,-legal,-build/include,-build/header_guard/', filewithpath]               
                output = subprocess.check_output(cmd)
                logfile.write(output.decode('ascii'))

При попытке запустить приведенный выше код выдается ошибка:

  File "C:\Python32\lib\site.py", line 159
    file=sys.stderr)
        ^ SyntaxError: invalid syntax Traceback (most recent call last):   File "C:\Users\me\Documents\dev\project\src\verifier.py", line 19, in <module>
    output = subprocess.check_output(cmd)   File "C:\Python32\lib\subprocess.py", line 511, in check_output
    raise CalledProcessError(retcode, cmd, output=output) subprocess.CalledProcessError: Command '['c:/Python27/python.exe', 'C:/users/me/Documents/dev/cpplint.py', '--filter=-whitespace,-legal,-build/include,-build/header_guard/', 'C:/users/me/Documents/dev/project/src/aboutdialog.cpp']' returned non-zero exit status 1

Если я заменю cmd чем-то более простым, например:

cmd=['C:/WinAVR-20100110/bin/avr-gcc.exe','--version']

Тогда скрипт работает как положено.

Я также пытался использовать одну строку команды вместо списка строк в качестве cmd, но результат тот же. При отладке кода я скопировал команду list-strings-turn-into-the-command-line-command из отладчика и запустил ее в командной строке Windows, и команда запустилась, как и ожидалось.

Интерпретатор Python, выполняющий мой скрипт, - это Python 3.2. Любые советы приветствуются.

Ответы [ 3 ]

11 голосов
/ 25 октября 2011

Похоже, cpplint.py просто завершает работу с ненулевым кодом возврата - что может произойти, например, если он обнаружит ошибки или "ошибки" в исходных файлах, которые он проверяет.

См.документация для subprocess.check_output .Обратите внимание, что если выполненная команда возвращает ненулевой код выхода , то вызывается subprocess.CalledProcessError.

Вы можете обойти это, наблюдая за CalledProcessError, например:

try:
    output = subprocess.check_output(cmd)
except subprocess.CalledProcessError as e:
    # ack!  cpplint.py failed... report an error to the user?

РЕДАКТИРОВАТЬ :

Кажется, что SyntaxErrorздесь, и, вероятно, это вызвано тем, что C:\Python32\lib находится в вашей PYTHONPATH (либо явно, либо, это может произойти, если это ваш текущий рабочий каталог).

Интерпретатор Python (начиная с версии 1.5.2)) автоматически запускается import site при запуске.Таким образом, когда это так, и ваш сценарий выполняется:

c:/Python27/python.exe C:/users/me/Documents/dev/cpplint.py ...

, тогда интерпретатор Python 2.7 сначала найдет C:\Python32\lib\site.py и попытается загрузить его вместоодин (предположительно) на C:\Python27\lib\site.py.Проблема заключается в том, что site.py в Python 3 содержит синтаксис, несовместимый с Python 2, поэтому процесс, запущенный subprocess.check_output, завершается с ошибкой SyntaxError, прежде чем он даже получит шанс запустить cpplint, который распространяет CalledProcessError.

Решение?Убедитесь, что Python2 получает истинный Python2 "PYTHONPATH", а также для Python3!Другими словами, убедитесь, что C:\Python32\lib не находится в пути поиска PYTHONPATH при запуске интерпретатора Python2.

Один из способов сделать это в вашем случае - установить явную среду при запуске процесса, например:

python2_env = {"PYTHONPATH": "path/to/python2/stuff:..."}
output = subprocess.check_output(cmd, env=python2_env)
1 голос
/ 20 февраля 2012

Я сделал это, заменив def main () следующим (я тоже редактирую функцию ошибки, чтобы получить правильный csv-файл):

errorlog = sys.stderr
sys.stderr = open("errorlog.csv","w")
sys.stderr.write("File;Line;Message;Category;Confidence\n")
for filename in filenames:
  ProcessFile(filename, _cpplint_state.verbose_level)
_cpplint_state.PrintErrorCounts()
sys.exit(_cpplint_state.error_count > 0)
sys.stdout = errorlog
sys.stderr.close()
1 голос
/ 25 октября 2011

Я бы попросил вас запустить этот первый

pipe = subprocess.Popen([cmd, options],stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, stderr = pipe.communicate()

Вы узнаете, что именно является причиной ошибки, поскольку CalledProcessError вызывается только в том случае, если код выхода был ненулевым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...