保持多个控制台窗口从批处理中打开

4

我如何编写批处理文件来顺序执行多个(Python)脚本,每个脚本在自己的窗口中运行,并在完成后保留所有这些窗口的打开状态?目前,我的批处理文件大致如下:

python script1
start python script2
pause/cmd

但只有父窗口保持打开状态。

谢谢。

环境: Windows XP/Vista


有很多种方法可以做到这一点。首先要问一些问题:您的原始脚本在整个过程中是否保持活动状态?您可以假定您对目录拥有写访问权限,例如%TEMP%目录或包含原始脚本的目录吗?您的原始脚本可以执行“sleep”可执行文件,并轮询Python脚本的完成情况吗?您想要执行多少个Python脚本,即是否合理使用一个巨大的长命令行来执行它们,还是太多了? - David I. McIntosh
你需要向脚本传递参数,还是总是使用简单的“python [脚本文件名]”来执行它们? - David I. McIntosh
第一条评论中的所有东西都可以。通常使用4-8个脚本,我愿意使用巨大的命令行,并没有传递参数。 - beets
3个回答

2

执行多个(Python)脚本,让它们依次在自己的窗口中运行,并在完成后保持所有这些窗口打开。

#!/usr/bin/env python
"""Continuation-passing style (CPS) script.

Usage:

   $ python cps.py script1.py arg1 arg2 -- script2.py a b c -- script3.py ...
"""
import platform
import sys
from subprocess import call

if len(sys.argv) < 2:
    sys.exit() # nothing to do

# define a command that starts new terminal
if platform.system() == "Windows":
    new_window_command = "cmd.exe /c start cmd.exe /c".split()
else:  #XXX this can be made more portable
    new_window_command = "x-terminal-emulator -e".split()

# find where script args end
end = sys.argv.index('--') if '--' in sys.argv else len(sys.argv)

# call script; wait while it ends; ignore errors
call([sys.executable] + sys.argv[1:end])

# start new window; call itself; pass the rest; ignore errors
rest = sys.argv[end+1:]
if rest:
    call(new_window_command + [sys.executable, sys.argv[0]] + rest)

print("Press Enter to exit") #NOTE: to avoid raw_input/input py3k shenanigans
sys.stdin.readline()

它支持在命令行中提供的脚本和其参数的数量。

如果您不使用脚本参数,则可以简化使用:

$ python cps.py script1.py script2.py script3.py

注意:脚本之间不要加--。在这种情况下,您需要修改代码:
  • end = 2设置为
  • rest = sys.argv[end:](注意:不要加+1

从cmd行中,我输入了python cps.py script01.py -- script02.py(其中所有三个脚本都与python.exe在同一个文件夹中)。这样可以正确执行script01,但是随后出现了WindowsError: [Error 2] The system cannot find the file specified的错误。我还尝试将其他文件作为script02,但问题仍然存在。有什么想法可能是问题所在吗?回溯信息在下一条评论中: - beets
Traceback报告: **文件**“cpsScript.py”,第32行,在<module>中 调用(new_window_command + [sys.executable,sys.argv [0]] + rest) **文件**“c:\ Python27 \ lib \ subprocess.py”,第493行,调用 返回Popen(* popenargs,\\ ** kwargs).wait() **文件**“c:\ Python27 \ lib \ subprocess.py”,第679行,初始化_ errread,errwrite) **文件**“c:\ Python27 \ lib \ subprocess.py”,第896行,_execute_child startupinfo) - beets
@beets: new_window_command 错误了。我已经更新了答案。 - jfs

2
如果你只有两个脚本,那么你的想法是正确的,只是语法有误:
start cmd.exe /k "python script1.py & start cmd.exe /k python script2.py"

如果您需要窗口标题:

start "Window1" cmd.exe /K "python script1.py & start "window2" cmd.exe /K python script2.py"

如果超过两个脚本,您将不得不使用更棘手的方法。以下.cmd文件将解决问题:

@echo off
if "%~1" == "recurse" goto runScript%~2

start "Window1" cmd /k "%~f0 recurse 1"
exit /b 0

:runScript1
python script1.py
start "Window2" cmd /k "%~f0 recurse 2"
exit /b 0

:runScript2
python script2.py
start "Window3" cmd /k "%~f0 recurse 3"
exit /b 0

:runScript3
python script3.py
exit /b 0

这个方法可以适用于任意数量的脚本或命令,并且可以为脚本设置任意参数等。如果您想让CMD窗口暂停并在按下键后消失:

@echo off
if "%~1" == "recurse" goto runScript%~2

start "Window1" cmd /c "%~f0 recurse 1"
exit /b 0

:runScript1
python script1.py
start "Window2" cmd /c "%~f0 recurse 2"
pause
exit /b 0

:runScript2
python script2.py
start "Window3" cmd /c "%~f0 recurse 3"
pause
exit /b 0

:runScript3
python script3.py
pause
exit /b 0

如果您希望在最终窗口按下一个键后立即终止所有程序:

@echo off
if "%~1" == "recurse" goto runScript%~2

start "Window1" cmd /c "%~f0 recurse 1"
exit /b 0

:runScript1
python script1.py
start "Window2" /wait cmd /c "%~f0 recurse 2"
exit /b 0

:runScript2
python script2.py
start "Window3" /wait cmd /c "%~f0 recurse 3"
exit /b 0

:runScript3
python script3.py
pause
exit /b 0

因此,您可以根据脚本的行为选择多种选项。


两个脚本选项非常好用。只是出于好奇,这是否可以嵌套超过两个脚本,或者除了可读性之外还有其他障碍?我明天会尝试更通用的解决方案。谢谢! - beets
如果你能够弄清楚引号的转义规则,你就可以使用Python生成命令行:print reduce(lambda cmd, script: r'start cmd.exe /k "python %s & %s"' % (script, cmd), reversed("1.py 2.py 3.py 4.py".split()), "echo done") - jfs
cmd.exe在解析和匹配引号方面表现不佳,而在解析和匹配括号方面则更差。我无法让它执行3个脚本,因此使用了其他代码。 - David I. McIntosh

0

您可以使用start命令打开一个新窗口(在后台使用/min),并运行一个命令。

start "window1" /min cmd.exe /c "pause"

最后一个命令“pause”可以是任何内容,但一定要将其放在引号中

要保持窗口打开状态,您应该将内容放在批处理脚本中,并将“pause”作为最后一条语句


我尝试了以下代码:start "window1" cmd.exe /c "python script1.py & pause" start "window2" cmd.exe /c "python script2.py & pause"但这会导致同时执行,而不是我想要的顺序执行。我还尝试使用/wait选项,但第一个脚本中的“pause”命令会阻止批处理文件继续执行下一个脚本。有没有一种方法可以保持窗口打开而不停止批处理文件? - beets

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接