26

The goal here is to run a new python file in a new shell from and existing python file in an existing shell. Say i have two files, aaa.py and bbb.py. Lets say for simplicity that all aaa.py does is...

subprocess.call('python bbb.py', shell=True)

...and lets say that bbb.py does is...

print 'It worked'

Now the goal is to run aaa.py in terminal 1 and get it to launch bbb.py in terminal 2. I would expect something like the command below to exist, but can't figure it out.

subprocess.call_in_new_window('python bb.py', shell=True)
Evan Cathcart
  • 635
  • 2
  • 10
  • 13
  • related: [Opening a Python thread in a new console window](http://stackoverflow.com/q/11712629/4279) – jfs Oct 14 '13 at 08:43
  • 1
    related: [keep multiple cmd windows open from batch](http://stackoverflow.com/q/12122535/4279) – jfs Oct 14 '13 at 09:02
  • See my answer here (related): http://stackoverflow.com/a/20612529/1882644 –  Dec 16 '13 at 13:52

3 Answers3

51

There's no way to do this in general from a shell. What you have to do is run the terminal program itself, or some launcher program that does so for you. And the way to do that is different for each terminal program.

In some cases, os.startfile will do what you want, but this isn't going to be universal.

Also, note in general, you're going to actually need an absolute path to your script, because the new terminal window will be running a new shell and therefore won't necessarily have your same working directory. But I'll ignore that for the examples.


With Windows cmd, the easiest way to do it is the start shell command. If the thing you start is any command-line program, including python, it will get a new cmd window. So, something like:

subprocess.call('start /wait python bb.py', shell=True)

OS X has a similar command, open. And it's a real program rather than a shell command, so you don't need shell=True. However, running a command-line program or script with open doesn't generally open a new terminal window. In fact, the whole point of it is to allow you to run programs as if they were being double-clicked in Finder, which never runs something in the terminal unless it's a .command file.

So, you can create a temporary .command wrapper file and open that; something like this (untested):

with tempfile.NamedTemporaryFile(suffix='.command') as f:
    f.write('#!/bin/sh\npython bb.py\n')
    subprocess.call(['open', '-W', f.name])

Alternatively, you can explicitly tell open to use Terminal.app, something like this:

subprocess.call(['open', '-W', '-a', 'Terminal.app', 'python', '--args', 'bb.py'])

Or you can script Terminal.app via AppleEvents. For example:

appscript.app('Terminal').do_script('python bb.py')

The "do script" event opens a new window and runs its argument as a command. If you want more detailed control, open the scripting dictionary in AppleScript Editor and see all the fun stuff you can do.


On Linux or other *nix systems… well, there are 65,102 different desktop environments, launchers, and terminal programs. Do you need to work on all of them?

With gnome-terminal, just running the terminal again gives you a new window, and the -x argument lets you specify an initial command, so:

subprocess.call(['gnome-terminal', '-x', 'python bb.py'])

Many older terminals try to be compatible with xterm, which does the same thing with -e, so:

subprocess.call(['xterm', '-e', 'python bb.py'])
subprocess.call(['rxvt', '-e', 'python bb.py'])

… etc.

How do you know which terminal the user is using? Good question. You could walk the like of parent processes from yourself until you find something that looks like a terminal. Or you could just assume everyone has xterm. Or you could look at how various distros configure a default terminal and search for all of them. Or…

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • in OS X the '--args' are used as argument to the Terminal.app, not the command line app (which is python in this case). So in this case the subprocess.call launches a Terminal app running python (ignoring the args). My workaround at the moment is to create a temp .sh script with the command line and the args and launch that script as the param in subprocess.call() ... kinda lame but i couldn't think of a better way. – Dexter Legaspi Nov 28 '13 at 04:26
  • Great answer, but I am wondering if you know how to accomplish this (running multiple terminals) on headless linux such as AWS ubuntu instance? I have a script that launches other scripts, but the 'gnome-terminal' parameter messes it all up because headless servers don't have any such GUI terminal installed. – alfredox Apr 11 '16 at 21:38
  • Helped me a lot. Now I try to close the terminal again but this is more difficult. I can't seem to be able to kill the process. If you could expand your answer with the instructions on how to close the terminal that would be excellent. – Si Mon Nov 22 '18 at 10:34
  • 1
    My only comment is that for Windows, using the form:`subprocess.call('start "" {}'.format(cmd), shell=True)` gave me the best results. – Frak Dec 11 '18 at 21:43
  • Is there any way to keep the terminal window open after it completes running? (i.e. return to a blinking cursor command line) – Praxiteles Apr 23 '20 at 14:27
17

This should probably be a comment, but since I can't yet...

In Windows , you can do:

subprocess.call('python bb.py', creationflags=subprocess.CREATE_NEW_CONSOLE)
Danyal
  • 528
  • 1
  • 7
  • 17
  • 3
    Is there any way to make the terminal window persistent so it doesn't close after the command completes? – Praxiteles Apr 23 '20 at 14:25
  • 2
    `import os ; os.system('start cmd /K python bb.py')` ... doing `/c` instead of `/K` would kill the new window after completion. – P S Solanki May 09 '21 at 10:05
  • Please Specify a command for the linux user – heyom Sep 04 '21 at 16:10
  • Can I close the first/main window after calling the second window? In other words, let's say I'm calling two things. The second one waits for the first one to finish/end. That's not how I want it. They should be called asynchronously. Is this possible? – akinuri Apr 21 '22 at 12:23
1

You won't be able to make that happen, at least not as simply as you are thinking about it. I suspect that you are talking about a Mac because of "terminal window".

You might be able to make it happen using the X Window system, but you will need a bunch of things to be set up, X-servers, permissions, etc. to make that happen.

These days, such things usually violate normal security boundaries. Say you download a program that behaves as you suggest. It brings up a window (terminal) (invisible to you) that has the same privileges that you have. It proceeds to read all of your directories and files and ships them to the originator of the program. You might not be happy with that. The whole time, you think you are playing a game, then you quit, and the second shell keeps running.

Windows and shells are a bit disjoint.

Fred Mitchell
  • 2,145
  • 2
  • 21
  • 29