【问题标题】:Why sometimes Python subprocess failed to get the correct exit code after running a process?为什么有时 Python 子进程在运行进程后无法获得正确的退出代码?
【发布时间】:2014-08-24 15:45:32
【问题描述】:

我正在使用 Python 子进程在 Windows 7 上运行外部脚本。我正在尝试获取退出代码。


在案例 1 中,我运行一个 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

因此,您可以看到在这种情况下子进程能够获得正确的退出代码。


在案例 2 中,我运行一个批处理文件 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

因此,您可以看到子进程在这种情况下也能够获得正确的退出代码。


在案例 3 中,我运行 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

在情况 3 中,当我在命令提示符下手动运行脚本时,它能够设置 %errorlevel%。当我使用 Python 子进程运行脚本时,子进程无法获取正确的退出代码。它总是返回 0。

案例3为什么Python子进程获取不到退出码?

【问题讨论】:

  • 为什么使用&lt;sikulicmd&gt; &lt;arg1&gt; &lt;arg2&gt; 运行jython 脚本?您手动运行的以echo %errorlevel% 结尾的确切命令是什么?您需要 jython 脚本的输出(stdout/stderr)吗?无关:为什么你需要python和jython? jython 就够了吗?
  • @J.F.Sebastian 嗨 Sebastian,我已经添加了更多问题描述。
  • 如果在 jython 脚本中添加长时间的停顿会发生什么?父 python 脚本是否等待它?试试:print(subprocess.call(r'C:\path\to\runsikuli.cmd -r C:\path\to\sikuli-script.sikuli &amp; echo %errorlevel%', shell=True))
  • @J.F.Sebastian 您好 Sebastian,我使用time.sleep(30) 在 Jython 脚本中添加了一个长时间的停顿。父 python 脚本等待它完成。当我运行此命令 print(subprocess.call(r'C:\path\to\runsikuli.cmd -r C:\path\to\sikuli-script.sikuli &amp; echo %errorlevel%', shell=True)) 时,它会打印出 Jython 脚本执行的所有输出。最后,它打印出 2 个退出代码,echo %errorlevel% 返回的 1,print(..) 返回的 1,都是 0。问题是,当我在命令提示符下手动运行相同的 Jython 脚本时,%errorlevel% 是正确设置。
  • 如果您在命令提示符(是 cmd.exe 还是 PowerShell ?)?

标签: python windows subprocess jython sikuli


【解决方案1】:

作为your comment says,如果您运行相同的命令,那么命令提示符和使用Python subprocess 模块都会产生相同的结果(0 退出代码)。

您可能会看到不同的退出代码,因为您使用了不同的命令。这里没有惊喜。 Python subprocess 模块返回正确的(对于给定命令)退出代码。


如果它没有返回正确的退出状态,那么您可以在 cmd.exe 命令的末尾添加 &amp; exit 作为解决方法以获得正确的返回码,请参阅 Python 问题跟踪器上的 "subprocess on Windows: wrong return code with shell=True"

from subprocess import check_call

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

【讨论】:

  • 嗨 Sebastian,该命令给出的退出代码为 0,因为您在 r'' 中给我的命令末尾添加了 &amp; echo %errorlevel%。当我在 cmd.exe 中运行我的原始命令(没有 &amp; echo ..),然后我在 cmd.exe 中手动运行 echo %errorlevel% 时,它会正确显示退出代码(不是 0)。当我将原始命令(不带 &amp; echo ..)复制粘贴到 Python 子进程中并运行它时,它显示退出代码为 0。
  • @PatrickL: no, you said: "两者 都是零。" echo %errrolevel% 打印上一个命令的退出代码,而不是 echo 命令本身。 是的,添加&amp; echo .. 使subprocess.call() 返回0。它不会使第一个命令返回0
  • 为了避免混淆,让我详细描述我使用的命令。当我在 cmd.exe 中运行C:\path\to\runsikuli.cmd -r C:\path\to\sikuli-script.sikuli,然后在 cmd.exe 中运行echo %errrolevel%,它显示16。当我在 cmd.exe 中运行您的命令 C:\path\to\runsikuli.cmd -r C:\path\to\sikuli-script.sikuli &amp; echo %errorlevel% 时,它显示 0。当我在 Python 子进程中运行r'C:\path\to\runsikuli.cmd -r C:\path\to\sikuli-script.sikuli' 并打印返回码时,它显示0
  • @PatrickL:如果你运行一个命令会发生什么,例如python -c "exit(11)" 之前 运行 ...runsikuli.cmd ...sikuli &amp; echo %errorlevel% 到底是打印11 还是0?如果你运行python -c "exit(12)",然后在cmd.exe 中运行echo %errorlevel%,会发生什么?如果你运行python -c "exit(13)" &amp; echo %errorlevel% 会发生什么?它是否显示13?如果你运行cmd /c "python -c "exit(14)"",然后在cmd.exe 中运行echo %errorlevel%,会发生什么? (您可能需要在内部引号" 之前添加^)。
  • 当我在运行...runsikuli.cmd ...sikuli &amp; echo %errorlevel% 之前运行python -c "exit(11)" 时,它会打印11。当我运行python -c "exit(12)" 然后运行echo %errorlevel% 时,它会打印12。当我运行python -c "exit(13)" &amp; echo %errorlevel% 时,它会打印12。当我在内部引号之前运行cmd /c "python -c "exit(14)""^ 时,它会打印14。当我在内部引号之前运行cmd /c "python -c "exit(14)"" 而没有^ 时,它会打印14。请注意,所有这些命令都在同一个 cmd.exe 窗口中按顺序运行。
【解决方案2】:

虽然这并不能直接回答问题,但是可以在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)

【讨论】:

    猜你喜欢
    • 2021-02-18
    • 2018-09-11
    • 1970-01-01
    • 2018-10-23
    • 2012-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多