Many Python programs operate as wrappers to other programs. For example, there are a wide variety of Python programs that work as a GUI wrapper for CLI programs. This tutorial uses an example from Programming Python: Powerful Object-Oriented Programming to demonstrate how a Python program can be used to launch another program.
Code
Parent Process
This code represents a parent process that is capable of launching a child process. I added my own comments to help further explain the code.
import os # Track the number of spawned children spawned_children = 0 # Enter an infinite loop while True: # Increment the number of children spawned_children += 1 # Now launch a new process # If we are still in the parent process, pid is non-zero # otherwise, pid is zero and indicates that we are in the # child process pid = os.fork() # Test if we are in the child process if pid == 0: # Now, since we are in the new process, we use # os.execlp to launch a child script. os.execlp('python', 'python', 'child.py', str(spawned_children)) assert False, 'error starting program' else: # If we are here, then we are still in the parent process print('Child is', pid) if input() == 'q': break
Child Process
This is a simple script that simply represents a sample child process.
import os, sys # Parent passes the child process number # as a command line argument print('Hello from child', os.getpid(), sys.argv[1])
Explanation
We have two core concepts used in this program. The first concept is forking the parent process into a child process. The other concept is actually launching a new program.
Forking
Forking is the process of launching a copy of the running program. The program that launched a copy of itself is called the parent process, while the copy of the program is called the child process. In theory, a parent and its children can spawn as many children as the underlying operating system allows.
The example program spawns a child process on line 16 and assigns the result to the variable called pid. When os.fork() returns, pid is zero if we are running in the child process or non-zero if we are still in the parent. The program uses an if – else statement (lines 19 and 25 respectively) to perform different operations depending if we are in the parent or child process.
The parent process executes lines 27 and 28. It simply prints out the child’s process id and then asks the user if they wish to continue the program. The user can enter ‘q’ to exit the parent process.
The child process executes code on lines 23 and 24. Line 23 uses os.execlp to start the companion child script and passes the number of spawned children as a command line argument. The child script prints its pid and the number of child processes and then exits.
Launching Programs
The Python os module provides a variety of ways to launch other programs via a Python script. This example makes use of os.execlp which looks for an executable on the operating system’s path. The first argument is the name of the program followed by any number of command line arguments.
The os.execlp is not supposed to return to the caller because if successful, the program is replaced by the new program. This is why it’s necessary to call os.fork() prior to using os.execlp (unless you wish your program to simply end with the new process). When the example script calls os.execlp, the child process created by os.fork is replaced by the new program launched by os.execlp.
Line 24 handles the case when os.execlp fails. Should os.execlp fail, control is returned back to the caller. In most cases, a develop should notify the user that launching the new program has failed. The example script accomplishes this by using an assert False statement with an error message.
References
Lutz, Mark. Programming Python. Beijing, OReilly, 2013.