Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incorrect exit code in python when calling windows script

Tags:

python

windows

I don't seem to be getting the correct exit code from subprocess.call on Windows.

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

Doing the same thing on windows seems to return something other than 0

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

Shouldn't the values from both calls give the same value? Am I doing something wrong?

In the worst case, how do I check the value of %errorlevel% in my python script?

UPDATE:

I tried something like this to get the errorlevel value:

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

However I do not see errorlevel in that dictionary (os.getenv['errorlevel'] also fails).

like image 402
Frank Flannigan Avatar asked Jul 09 '11 21:07

Frank Flannigan


1 Answers

A process exit code and the errorlevel environment variable aren't the same:

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 will set the errorlevel to 1, but that's no longer available after the shell exits. proc_fail, however, sets the process exit code to 1. The only solution that comes to mind is a wrapper batch file that calls ant.bat and sets the process exit code according to the errorlevel:

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

Edit:

Your update got me thinking about an alternate approach using Popen. You can run the batch file via cmd's /K option, which will run a command without exiting. Then simply send exit %errorlevel% via stdin, and communicate():

#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
like image 118
Eryk Sun Avatar answered Oct 06 '22 00:10

Eryk Sun