4

How can I make a batch file execute multiple (Python) scripts sequentially, each in their own window, and keep all those windows open upon completion? Right now, my batch is something like:

python script1
start python script2
pause/cmd

But only the parent window stays open.

thanks.

Environment: Windows XP/Vista

Eryk Sun
34.5k7 gold badges97 silver badges113 bronze badges
asked Aug 25, 2012 at 13:47
3
  • There are a lot of ways of doing it. Some questions first: Is it OK to have your original script stay alive for the duration? Can you assume you have write-access to a directory, e.g. the %TEMP% directory or the directory containing the original script? Is it OK to have your original script execute a "sleep" executable and poll for completion of the python scripts? roughly how many python scripts do you want to execute, i.e. is it reasonable to have one huge long command line that executes them all, or are there too many? Commented Aug 26, 2012 at 22:31
  • And do you need to pass parameters to your scripts, or are you always executing them with just a simple "python [scriptFileName]"? Commented Aug 26, 2012 at 22:37
  • Yes to everything in the first comment. About 4-8 scripts would probably be typical usage. I'd be willing to use a huge command line. No parameters being passed. Commented Aug 27, 2012 at 2:00

3 Answers 3

2

[to] execute multiple (Python) scripts sequentially, each in their own window, and keep all those windows open upon completion

#!/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()

It supports as many scripts with their arguments as you can supply on the command line.

If you don't use arguments for scripts; you could simplify the usage:

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

Note: no -- between scripts. You need to modify the code in this case:

  • set end = 2
  • and rest = sys.argv[end:] (Note: no +1)
answered Aug 27, 2012 at 14:39
Sign up to request clarification or add additional context in comments.

3 Comments

From the cmd line I entered python cps.py script01.py -- script02.py (where all three scripts were in the same folder as python.exe). This executed script01 properly but then stopped with a WindowsError: [Error 2] The system cannot find the file specified. I also tried this with other files as script02. Any ideas on what may be the problem? Traceback is in next comment:
The Traceback was ` File "cpsScript.py", line 32, in <module> call(new_window_command + [sys.executable, sys.argv[0]] + rest) File "c:\Python27\lib\subprocess.py", line 493, in call return Popen(*popenargs, **kwargs).wait() File "c:\Python27\lib\subprocess.py", line 679, in init_ errread, errwrite) File "c:\Python27\lib\subprocess.py", line 896, in _execute_child startupinfo)`
@beets: new_window_command was wrong. I've updated the answer
2

If you have only two scripts, you had the right idea, just got your syntax wrong:

start cmd.exe /k "python script1.py & start cmd.exe /k python script2.py"

If you need window titles:

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

Any more than two scripts, and you will have to resort to trickier stuff. The following .cmd file will do the trick:

@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

And this is scalable to any number of scripts or commands, with arbitrary parameters to the scripts, etc. If you want the cmd windows to just pause, and disappear when you press a key:

@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

If you want them all to terminate instantly at the press of one key on the final window:

@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

So, you have lots of options for behaviour of the script.

answered Aug 26, 2012 at 22:48

3 Comments

The two-script option works great. Just out of curiosity, is this nestable beyond two scripts, or is there some barrier aside from just readability? I'll try the more general solution tomorrow. Thanks!
If you can figure out the escaping rules for quotes you could generate the command line using 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")
cmd.exe does a poor job of parsing and matching quotes, and an even poorer job of parsing and matching brackets. I was unable to get it to do 3 scripts, hence the other code.
0

You can use the start command to open a new window (in the background with /min) and run a command

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

The final command, pause can be anything, just be sure to put it all in quotes

To keep a window open, you should place the content in a batch script with a pause as the last statement

answered Aug 25, 2012 at 13:53

1 Comment

I tried: start "window1" cmd.exe /c "python script1.py & pause" start "window2" cmd.exe /c "python script2.py & pause" But this results in simultaneous execution, rather than the sequential execution that want. I also tried using the /wait option, but the "pause" command in the first script stops the batch file from proceeding to the next script. Is there a way to hold the window open that doesn't stop the batch file?

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.