调用Windows脚本时Python返回错误退出代码
我在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 个回答
-1
os.system('ant.bat fail')
这段代码正好实现了你想要的功能。它会返回错误级别的信息。
0
我通过使用批处理中的 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
是个好主意,这样可以传递错误信息(大致相当于 bash 中的 set -e
)。
8
进程的退出代码和错误级别环境变量其实是两回事:
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。你可以通过cmd的/K选项来运行批处理文件,这样可以在不退出的情况下执行命令。然后只需通过标准输入发送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