Forkert afgangskode i python, når du ringer til Windows-script

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg synes ikke at få den korrekte exitkode fra subprocess.call på Windows.


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


At gøre det samme på Windows ser ud til at returnere noget andet end 0


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


Skal værdierne fra begge opkald give samme værdi? Gør jeg noget galt?


I værste fald, hvordan kontrollerer jeg værdien af\% errorlevel\% i mit python script?


UPDATE:


Jeg forsøgte noget som dette for at få fejlværdiernes værdi:


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


Men jeg kan ikke se errorlevel i den ordbog (os.getenv [['errorlevel']] svigter også).

Bedste reference


En procesudgangskode og fejlmiljøets miljøvariabel er ikke ens:


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 vil sætte errorlevel til 1, men det er ikke længere tilgængeligt efter at shell'en udløber. proc\_fail indstiller dog procesudgangskoden til 1. Den eneste løsning, der kommer til at tænke på, er en wrapper-batchfil, der kalder ant.bat og indstiller procesudgangskoden i henhold til 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





Din opdatering fik mig til at tænke på en alternativ tilgang ved hjælp af Popen. Du kan køre batchfilen via cmd 's/K-indstillingen, som vil køre en kommando uden at lukke. Så send blot exit \%errorlevel\% via stdin og kommunikerer ():


#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\%
')
>>> 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\%
')
>>> p.returncode
0

Andre referencer 1


Jeg kunne få den korrekte adfærd ved at bruge kommandoen call, som [15]


cmd = [os.environ['COMSPEC'], '/c', 'call', bat\_file]
try:
    subprocess.check\_call(cmd)
except subprocess.CalledProcessError:
    # Error handling code


(Jeg brugte subprocess.check\_call men subprocess.call burde arbejde på samme måde).


Det er også altid en god idé at sætte if errorlevel 1 exit 1 efter hver kommando i dit batch script, for at udbrede fejlene (omtrent lig med bashs set -e).

Andre referencer 2


os.system('ant.bat fail') gør præcis hvad du vil. Det returnerer fejlniveauet.