My ultimate goal is to let my python script launch a child process, in another terminal, that runs independently from the parent:
When the parent process finishes, the child process should continue. It should not be killed.
The parent process should be able to either wait for the child to finish, or just continue its own stuff.
I achieved the goal with the script below. Please note that the child process I chose to launch is python3 child.py, but it can be anything else (and doesn't have to be a python process). Also note that, in this case, I let the parent process wait for the child process by adding the .communicate() in the end.
# Script parent.py
# ================
import subprocess, shutil
if __name__ == '__main__':
print('Launch child process')
p = subprocess.Popen(
['x-terminal-emulator', '-e', 'python3', 'child.py'],
).communicate()
print('Child process finished')
exit(0)
I then launch the parent:
$ python3 parent.py
It works great. The parent first prints 'Launch child process', then the child process appears in another terminal. The child does its things, then closes. After the child closes, the parent prints 'Child process finished'. Great!
Unfortunately, The x-terminal-emulator is only present on Debian and derivatives. My goal is to make this approach work on most Linux systems.
The most sensible approach I could find so far, would be to try out a few default 'terminal emulators' that are present on the most common Linux distros. For example:
'gnome-terminal''konsole''xterm''urxvt''rxvt''termit''terminator'$TERMINAL(this is a non-standard variable)
I tried with 'gnome-terminal' to get started, but it already goes wrong:
# Script parent.py
# ================
import subprocess, shutil
if __name__ == '__main__':
print('Launch child process')
# For the 'gnome-terminal', the '-e' argument is deprecated.
# One should use the '--' argument instead.
p = subprocess.Popen(
['gnome-terminal', '--', 'python3', 'child.py'],
).communicate()
print('Child process finished')
exit(0)
The child process launches, but the parent doesn't wait for it to finish - even though I instructed it explicitely to do so by adding the .communicate() at the end of Popen(..).
In other words, the parent prints 'Child process finished' immediately, before the child has actually finished.
Question 1:
Why is this approach working for 'x-terminal-emulator' and not for 'gnome-terminal'? PS: I'm working on Ubuntu.
EDIT: I found the solution to this problem. One has to add the --wait flag to tell the gnome-terminal not to return until its child process exits.
Question 2:
How can I get this approach working on most Linux systems? If I try to launch any other terminal emulator like xterm, konsole, ... should I expect similar problems? I can't test right now, because I only have Ubuntu for the moment.
I believe I have a reasonably good approach now. I list the most common terminal emulators in Linux, and loop over them to see which one is present on the system. Then I launch the child process in that terminal.
There are a few subtle differences between the terminals. I've installed some on my Ubuntu to figure out. This is what I have so far:
Please let me know if I forgot one of the "big" ones, or if I made any mistakes in launching some of these terminals.
If you want to test this script, just copy-paste it into a
parent.pyfile. You'll also need achild.pyfile in the same folder. Thatchild.pyfile can be anything. Feel free to take this sample code:Then run the parent like so: