【问题标题】:Python to close own CMD shell window on exitPython在退出时关闭自己的CMD shell窗口
【发布时间】:2018-04-03 01:09:49
【问题描述】:

我正在运行多个进程(数百个),每个进程都在 python 中并使用以下方法调用:

command = 'start cmd /k call python %s' % (some_py_prog)
os.system(command)

/k 在执行后打开 cmd 窗口的位置。这很适合检查错误。然而,当我调用数百个作业时,我的屏幕变得杂乱无章。

那么如何让python仅在成功完成时关闭自己的主机cmd窗口?我需要错误的作业保持可见。

【问题讨论】:

  • 为什么要使用 Python 脚本来启动运行 Python 脚本的 shell 窗口,而不是使用 Python 脚本导入和运行其他 Python 脚本/函数(应该这样做)?跨度>
  • 内存管理。如果我从一个 python 脚本调用尽可能多的作业,顶级命名空间会增长并调用操作系统以获得更多。没关系,但是我发现只有在整个python程序完成时才会释放这个内存(即使你使用gc.collect(),操作系统仍然会标记正在使用的空间)。通过这种方式,命名空间被分离,并且为每个命名空间分配的内存由操作系统在每个 python 子程序关闭时释放。子程序使用其他程序(由 MS 和第 3 方,由我的工作强制) - 这是我发现管理系统内存 OK 的唯一方法。

标签: python windows cmd


【解决方案1】:

简短回答:只需使用 /c 而不是 /k 将导致 cmd 脚本在命令终止后立即退出,这就是您所要求的:

command = 'start cmd /c call python %s' % (some_py_prog)
os.system(command)

但是您在这里堆叠了一些不必要的cmd.exe:一个用于os.system 调用,一个用于显式cmd.c。你可以简单地使用subprocess 模块:

subprocess.call('python %s' % (some_py_prog), 
    creationflags = subprocess.CREATE_NEW_CONSOLE)

创建标志足以要求系统在新控制台中启动新进程,该控制台将在命令终止后立即关闭。可选地,如果您需要它来预处理一些 cmd 好东西,例如 io 重定向,您可以添加 shell=True 选项。

(在我的其他answer 中提供更多详细信息,特别是在 eryksun 的评论中)

【讨论】:

  • 如果您想在出现错误时保持新控制台打开,您可以使用'python -i %s' 运行它。如果您使用的是 py 启动器,还可以将 -i 选项添加到 shebang。
【解决方案2】:

让我们首先分析一下两个发布的 Python 脚本行在执行 Python 脚本时的实际作用。感谢 eryksun 他对真正使用 Python 的深入调查得出了正确的描述,现在可以在下面阅读。

os.system() 导致在前台使用控制台窗口执行 cmd.exe /C 并暂停 Python 脚本的执行,直到 Windows 命令解释器终止。如果 Python 脚本本身在控制台中执行,则启动的 cmd.exe 会继承此控制台。

这个命令进程以start 开始,这是一个cmd.exe 的内部命令,还有一个带有前台控制台窗口的命令进程。很好,但是第二个命令进程在完成命令执行后立即终止。如果您想查看执行的脚本或 Python 解释器本身在运行 Python 脚本时输出的错误,那就不太好。

所以第二个命令进程以/k 选项启动cmd.exe 以继续运行此命令进程,继承start 创建的控制台,并在完成指定命令执行后打开控制台窗口。

第二个命令进程运行内部命令call,这根本没有必要,因为python 是真正的python.exe,一个控制台应用程序而不是一个批处理文件。因此,call 根本不需要。

建议始终使用完整的文件名指定应用程序和脚本,即文件名 + 文件扩展名,而不仅仅是文件名。如果可执行文件/脚本的路径已知且固定,则也应指定它。这使得应用程序/脚本的执行独立于当前目录和环境变量PATHEXTPATH

Python 解释器在第二个控制台中执行指定的 Python 脚本。

os.system() 开始的第一个命令进程在start 完成后立即终止,这在cmd.exe /k 开始后已经发生,而python.exe 正在解释Py​​thon 脚本。

剩下的就是运行 Python 解释器和脚本的第二个命令进程。即使 Python 解释器在完成指定 Python 脚本的执行后终止,此命令进程也会继续运行。

因此,目标是在 Python 解释器完成 Python 脚本的执行后也使用控制台窗口终止第二个命令进程,但前提是在执行脚本时没有发生错误。

好吧,我根本没有安装 Python,但我想它会在执行脚本时出现错误并以大于 0 的返回码退出。否则脚本成功执行时退出码为 0。

所以使用这样的命令可能会起作用:

command = 'start cmd.exe /K python.exe %s ^&^& exit' % (some_py_prog)
os.system(command)

start cmd.exe /K 开头的第二个命令进程执行的命令行现在包含两个命令:

  1. Python 解释器 python.exe 将脚本作为参数执行
  2. 内部命令exit,只有当第一个命令的退出代码是0,因为操作员&&,才应该由Windows命令解释器执行第二个命令。

请参阅Single line with multiple commands using Windows batch file 上的答案,了解有关要执行多个命令的单个命令行的详细信息。

每个&符号必须在此处使用 Windows 命令解释器的转义字符进行转义,即插入符号 ^。这是必要的,否则&& 将被运行start 的第一个命令进程解释为在成功执行start 后运行的附加命令。

请注意,我没有安装 Python,因此仅在命令提示符窗口中使用批处理文件 Test.bat 和单个命令行 @echo %~dp0 executed. & exit /B 1 进行了以下测试。

start cmd.exe /K call Test.bat ^&^& exit

Test.bat 是一个批处理文件,而不是需要使用命令call 的可执行文件。没有特定窗口标题的已启动命令进程保持打开状态,因为Test.bat 退出并返回代码 1。如果我在 Test.bat 中修改命令行末尾的数字 1 到 0,启动的命令进程将自行退出。

当然,在使用此解决方案时脚本代码检测到错误时,脚本代码本身需要暂停脚本执行。

【讨论】:

  • 谢谢莫菲!这很有效,让我可以看到错误的进程在做什么/确定了要修复的错误。我知道在 16,128 个已发布的工作中,有一个(某处)只有 16,023 个回来了...... :) 谢谢你!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-16
  • 2014-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多