Неверный код выхода в python при вызове скрипта Windows - PullRequest
6 голосов
/ 10 июля 2011

Кажется, я не получаю правильный код завершения из subprocess.call в Windows.

import subprocess
exit_code = subprocess.call(['ant.bat', 'fail'])
print exit_code # prints 0

Похоже, что то же самое в Windows возвращает что-то отличное от 0

> echo %errorlevel%
0
> ant fail
> echo %errorlevel%
1

Разве значения обоих вызовов не должны давать одно и то же значение? Я что-то не так делаю?

В худшем случае, как проверить значение% errorlevel% в моем скрипте python?

UPDATE:

Я пытался что-то вроде этого, чтобы получить значение уровня ошибки:

environment = os.environment.copy()
cmd = subprocess.Popen(['ant.bat', 'fail'], env = environment)
for key, value in environment.items():
    print '%s = %s' % (key, value)

Однако я не вижу уровень ошибки в этом словаре (os.getenv ['errorlevel'] также не работает).

Ответы [ 3 ]

8 голосов
/ 10 июля 2011

Код завершения процесса и переменная среды errorlevel не совпадают:

ant.bat:

if "%1"=="batch_fail" exit /B 1
if "%1"=="proc_fail" exit 1


>>> import subprocess
>>> subprocess.call(['ant.bat', 'batch_fail'])
0
>>> subprocess.call(['ant.bat', 'proc_fail'])
1

batch_fail установит уровень ошибки в 1, но он больше не доступен после выхода из оболочки.Однако proc_fail устанавливает код завершения процесса равным 1. Единственное решение, которое приходит на ум - это пакетный файл-обертка, который вызывает ant.bat и устанавливает код завершения процесса в соответствии с уровнем ошибки:

ant_wrapper.bat:

@echo off
call ant.bat %1
if errorlevel 1 exit 1

>>> subprocess.call(['ant_wrapper.bat'])
0
>>> subprocess.call(['ant_wrapper.bat', 'batch_fail'])
1
>>> subprocess.call(['ant_wrapper.bat', 'proc_fail'])
1

Редактировать:

Ваше обновление заставило меня задуматься об альтернативном подходе с использованием Popen.Вы можете запустить командный файл с помощью параметра / K команды cmd, который будет запускать команду без выхода.Затем просто отправьте exit %errorlevel% через стандартный ввод и сообщите ():

#test errorlevel==1
>>> p = subprocess.Popen(['cmd', '/K', 'ant.bat', 'batch_fail'], 
      stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>> stdoutdata, stderrdata = p.communicate(b'exit %errorlevel%\r\n')
>>> p.returncode
1

#test errorlevel==0
>>> p = subprocess.Popen(['cmd', '/K', 'ant.bat'], 
      stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>> stdoutdata, stderrdata = p.communicate(b'exit %errorlevel%\r\n')
>>> p.returncode
0
0 голосов
/ 18 февраля 2015

Мне удалось получить правильное поведение с помощью пакетной call команды , например

cmd = [os.environ['COMSPEC'], '/c', 'call', bat_file]
try:
    subprocess.check_call(cmd)
except subprocess.CalledProcessError:
    # Error handling code

(я использовал subprocess.check_call, но subprocess.call должен работать так же).

Также всегда полезно ставить if errorlevel 1 exit 1 после каждой команды в вашем пакетном скрипте, чтобы распространять ошибки (примерно эквивалент set -e bash).

0 голосов
/ 15 апреля 2014

os.system('ant.bat fail') делает именно то, что вы хотите.Возвращает уровень ошибки.

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