为什么有时Python子进程无法获取正确的退出代码?

5 投票
2 回答
7923 浏览
提问于 2025-04-18 12:00

我在Windows 7上使用Python的subprocess模块来运行外部脚本。我想获取这些脚本的退出代码。


在第一种情况下,我运行了一个Python脚本 test1.py

test1.py

import sys
sys.exit(24)   <--exit code

myscript1.py

import subprocess
process = subprocess.Popen(["python", "C:\\path\\to\\test1.py"], stdout=subprocess.PIPE)
process.wait()
print process.returncode

在Windows命令提示符下,当我运行这个脚本时,我得到了以下输出:

>python test1.py
>
>echo %errorlevel%
>24
>
>python myscript1.py
>24

所以,你可以看到在这种情况下,subprocess能够正确获取退出代码。


在第二种情况下,我运行了一个批处理文件 test2.cmd

test2.cmd

EXIT /B 56   <--exit code

myscript2.py

import subprocess
process = subprocess.Popen(["C:\\path\\to\\test2.cmd"], stdout=subprocess.PIPE)
process.wait()
print process.returncode

在Windows命令提示符下,当我运行这个脚本时,我得到了以下输出:

>test2.cmd
>
>echo %errorlevel%
>56
>
>python myscript2.py
>56

所以,你可以看到在这种情况下,subprocess也能够正确获取退出代码。


在第三种情况下,我运行了一个SikuliX脚本。

test3.sikuli

xxx xxx (sikuli script here)
xxx xxx
...
exit(16)   <--exit code

myscript3.py

import subprocess
process = subprocess.Popen(["C:\\path\\to\\runsikuli.cmd", "-r", "C:\\path\\to\\sikuli-script.sikuli"], stdout=subprocess.PIPE)
process.wait()
print process.returncode

在Windows命令提示符下,当我运行这个脚本时,我得到了以下输出:

>C:\path\to\runsikuli.cmd -r C:\path\to\sikuli-script.sikuli
>... (stdout + stderr)
>16
>
>echo %errorlevel%
>16
>
>python myscript3.py
>0

在第三种情况下,当我在命令提示符下手动运行这个脚本时,它能够设置%errorlevel%。但是当我使用Python的subprocess来运行这个脚本时,subprocess却无法获取正确的退出代码。它总是返回0。

为什么在第三种情况下,Python的subprocess无法获取退出代码呢?

2 个回答

0

虽然这并没有直接回答问题,但你可以用这种方法间接获取Python子进程的退出代码。

首先,创建一个批处理文件 batch.cmd。在这个文件里,像这样调用你想执行的命令:

call %1 -r %2
EXIT /B %errorlevel%

然后在你的Python脚本中:

import subprocess
exitcode = subprocess.call(r'C:\path\to\batch.cmd C:\path\to\runsikuli.cmd C:\path\to\sikuli-script.sikuli', shell=True)
print "Exit Code = "+str(exitcode)
3

正如你提到的,如果你运行相同的命令,那么无论是在命令提示符下还是使用Python的subprocess模块,都会得到相同的结果(退出代码为0)。

你可能会看到不同的退出代码,因为你使用了不同的命令。这并不奇怪。Python的subprocess模块会返回正确的(针对特定命令)退出代码。


如果它没有返回正确的退出状态,你可以在cmd.exe命令的末尾加上& exit,作为一种解决方法来获取正确的返回代码,具体可以查看“Windows上的subprocess:shell=True时返回错误代码”在Python问题追踪器上的内容:

from subprocess import check_call

check_call(r'C:\path\to\runsikuli.cmd -r C:\path\to\sikuli-script.sikuli & exit',
           shell=True)

撰写回答