当 运行 在 python 中使用 Popen 进行子处理并启动 /wait 时无法获取退出代码
Cannot get exit code when running subprocesses in python using Popen and start /wait
我正在尝试创建一个 python 脚本来启动一个新的 window 并等待它完成,然后检索退出代码。所以我使用带 start /wait
的 Popen 为它创建一个单独的 window,但这不能正确转发退出代码。
这段代码总结了问题:
import subprocess
params = {}
params['stdout'] = subprocess.PIPE
params['stderr'] = subprocess.PIPE
params['shell'] = True
proc = subprocess.Popen('start /wait cmd /c exit 1', **params)
# This works but the above line does not
#proc = subprocess.Popen('exit 1', **params)
resultCode = proc.wait()
print(resultCode)
start /wait
的文档建议它应该 return 退出代码,当我手动 运行 然后检查 %ERRORLEVEL%
它看起来正确,所以我我不确定我做错了什么
正在使用
proc = subprocess.Popen('call cmd /c exit 1', **params)
而不是你的 start /wait
returns resultCode
中的错误代码 1。
按此问答逻辑:CALL command vs. START with /WAIT option
我的猜测是,区别在于 start /wait
不与同一环境共享变量,而 call
是。
如果通过 CreateProcess
或 ShellExecuteEx
成功执行给定命令,CMD 的 start
命令总能成功。即使指示 /wait
并最终将 %errorlevel%
设置为非零值,它也会成功。你可以通过 运行ning (start /wait exit 1) && echo success
看到这一点。 &&
运算符仅在左侧表达式成功时才执行右侧表达式。
要解决此问题,您可以使用 start
设置的 !errorlevel!
值手动退出初始 shell。例如:
command = 'exit 1'
shell_path = os.environ.get('ComSpec', 'cmd.exe')
start_command = 'start "" /wait {}'.format(command)
cmdline = '"{shell}" /v:on /c "({command}) & exit !errorlevel!"'.format(
shell=shell_path, command=start_command)
proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
请注意,上面的 Popen
调用不使用 shell=True
参数,因为 shell 需要使用 /v:on
选项手动 运行。这允许延迟扩展环境变量,使用“!”而不是“%”。
就是说,对于您声明的 objective,您不需要 shell。只需让子进程通过传递 CREATE_NEW_CONSOLE
创建标志来创建一个新的控制台,如下所示:
proc = subprocess.Popen(args, creationflags=subprocess.CREATE_NEW_CONSOLE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
我正在尝试创建一个 python 脚本来启动一个新的 window 并等待它完成,然后检索退出代码。所以我使用带 start /wait
的 Popen 为它创建一个单独的 window,但这不能正确转发退出代码。
这段代码总结了问题:
import subprocess
params = {}
params['stdout'] = subprocess.PIPE
params['stderr'] = subprocess.PIPE
params['shell'] = True
proc = subprocess.Popen('start /wait cmd /c exit 1', **params)
# This works but the above line does not
#proc = subprocess.Popen('exit 1', **params)
resultCode = proc.wait()
print(resultCode)
start /wait
的文档建议它应该 return 退出代码,当我手动 运行 然后检查 %ERRORLEVEL%
它看起来正确,所以我我不确定我做错了什么
正在使用
proc = subprocess.Popen('call cmd /c exit 1', **params)
而不是你的 start /wait
returns resultCode
中的错误代码 1。
按此问答逻辑:CALL command vs. START with /WAIT option
我的猜测是,区别在于 start /wait
不与同一环境共享变量,而 call
是。
CreateProcess
或 ShellExecuteEx
成功执行给定命令,CMD 的 start
命令总能成功。即使指示 /wait
并最终将 %errorlevel%
设置为非零值,它也会成功。你可以通过 运行ning (start /wait exit 1) && echo success
看到这一点。 &&
运算符仅在左侧表达式成功时才执行右侧表达式。
要解决此问题,您可以使用 start
设置的 !errorlevel!
值手动退出初始 shell。例如:
command = 'exit 1'
shell_path = os.environ.get('ComSpec', 'cmd.exe')
start_command = 'start "" /wait {}'.format(command)
cmdline = '"{shell}" /v:on /c "({command}) & exit !errorlevel!"'.format(
shell=shell_path, command=start_command)
proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
请注意,上面的 Popen
调用不使用 shell=True
参数,因为 shell 需要使用 /v:on
选项手动 运行。这允许延迟扩展环境变量,使用“!”而不是“%”。
就是说,对于您声明的 objective,您不需要 shell。只需让子进程通过传递 CREATE_NEW_CONSOLE
创建标志来创建一个新的控制台,如下所示:
proc = subprocess.Popen(args, creationflags=subprocess.CREATE_NEW_CONSOLE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)