调用windows脚本时python中的退出代码不正确

时间:2011-07-09 21:07:33

标签: python windows

我似乎没有从Windows上的subprocess.call获取正确的退出代码。

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

在Windows上做同样的事情似乎返回0以外的东西

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

两个调用的值不应该给出相同的值吗?我做错了吗?

在最坏的情况下,如何在我的python脚本中检查%errorlevel%的值?

更新:

我尝试过这样的东西来获取errorlevel值:

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

但是我没有在该字典中看到errorlevel(os.getenv ['errorlevel']也失败了。)

3 个答案:

答案 0 :(得分:8)

进程退出代码和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会将errorlevel设置为1,但在shell退出后不再可用。但是,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的替代方法。您可以通过cmd / K选项运行批处理文件,该选项将在不退出的情况下运行命令。然后只需通过stdin发送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

答案 1 :(得分:0)

我可以使用批处理call command来获得正确的行为,例如

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以传播错误(大致相当于bash&#39; s set -e)也是一个好主意。< / p>

答案 2 :(得分:-1)

os.system('ant.bat fail')完全符合您的要求。它确实返回错误级别。