Last Updated on September 12, 2022
You can get all active child processes via the multiprocessing.active_children() function.
In this tutorial you will discover how to get all active child processes in Python.
Let’s get started.
Need to Get Active Child Processes
A process is a running instance of a computer program.
Every Python program is executed in a Process, which is a new instance of the Python interpreter. This process has the name MainProcess and has one thread used to execute the program instructions called the MainThread. Both processes and threads are created and managed by the underlying operating system.
Sometimes we may need to create new child processes in our program in order to execute code concurrently.
Python provides the ability to create and manage new processes via the multiprocessing.Process class.
You can learn more about multiprocessing in the tutorial:
In concurrent programming, we sometimes need to get all active child processes.
This may be for many reasons, such as:
- Log or report the status of the application.
- Conditionally execute code based on the number or specific child processes running.
- Block and wait for all active child processes to terminate.
How can we get all active child processes?
Run loops using all CPUs, download your FREE book to learn how.
How to Get Active Child Processes
We can get all active child processes via the multiprocessing.active_children() function.
The function will return a list of multiprocessing.Process instances, one for each child of the current process that is currently alive and running.
For example:
1 2 3 |
... # get all active child processes children = multiprocessing.active_children() |
If all child processes have finished, then the multiprocessing.active_children() will return an empty list.
Similarly, if the process did not start any child process, then the function will return an empty list.
If a child of the current process itself creates a child process, then it will not appear in the list of active child processes for the current process. The function returns a list of child processes only for the current process.
Now that we are familiar with how to get all active child processes, let’s look at some worked examples.
Example of No Child Processes
We can explore how to get child processes for the main process that does not have not started any child processes.
In this example, we expect the main process to have no child processes and the list returned from multiprocessing.active_children() to be empty.
The complete example is listed below.
1 2 3 4 5 6 7 8 |
# SuperFastPython.com # get all active child processes for the main process with no children from multiprocessing import active_children # get all active child processes children = active_children() # report details print(f'Active Children: {len(children)}') print(children) |
Running the example gets all the active child processes for the current main process.
As expected, we can see that the main process has no active processes.
1 2 |
Active Children: 0 [] |
Next, let’s explore actually starting a suite of child processes and then getting a list of those active processes.
Free Python Multiprocessing Course
Download your FREE multiprocessing PDF cheat sheet and get BONUS access to my free 7-day crash course on the multiprocessing API.
Discover how to use the Python multiprocessing module including how to create and start child processes and how to use a mutex locks and semaphores.
Example of Getting All Active Child Processes
We can explore how to get active child processes for a process that has many active child processes running.
In this example, we will start a suite of child processes in the main process, have the child processes block for a moment and then have the main process access and report the details of all active child processes.
Firstly, we can define a function that will execute in the child processes.
This function will block for one second, allowing the main process to gather the list of active child processes.
The task() function below implements this.
1 2 3 4 |
# function to execute in a new process def task(): # block for a moment sleep(1) |
Next, in the main process, we will create and start ten processes configured to execute our custom task function.
1 2 3 4 5 |
... # configure and start child processes for _ in range(10): # create and start child process Process(target=task).start() |
The main process will then block a moment to allow the child processes to start up.
1 2 3 |
... # wait a moment sleep(0.3) |
Next, we can get a list of all child processes, and report their details.
1 2 3 4 5 6 7 |
... # get all active child processes children = active_children() # report details print(f'Active Children: {len(children)}') for child in children: print(child) |
Finally, the main process will block until all child processes terminate.
1 2 3 4 |
... # block until all children are finished for child in children: child.join() |
Tying this together, the complete example is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# SuperFastPython.com # get all active child processes from time import sleep from multiprocessing import active_children from multiprocessing import Process # function to execute in a new process def task(): # block for a moment sleep(1) # protect the entry point if __name__ == '__main__': # configure and start child processes for _ in range(10): # create and start child process Process(target=task).start() # wait a moment sleep(0.3) # get all active child processes children = active_children() # report details print(f'Active Children: {len(children)}') for child in children: print(child) # block until all children are finished for child in children: child.join() |
Running the example first starts ten child processes.
The main process then blocks for a fraction of a second. All children process start-up and block for one second.
The main process then gets a list of all active child processes. This list contains a multiprocessing.Process instance for each of the ten processes that we started.
The total number of active child processes is reported and the details including the name, pid and parent pid are then reported.
Finally, the main process blocks waiting for all child processes to start.
1 2 3 4 5 6 7 8 9 10 11 |
Active Children: 10 <Process name='Process-8' pid=12469 parent=12460 started> <Process name='Process-10' pid=12471 parent=12460 started> <Process name='Process-3' pid=12464 parent=12460 started> <Process name='Process-6' pid=12467 parent=12460 started> <Process name='Process-2' pid=12463 parent=12460 started> <Process name='Process-4' pid=12465 parent=12460 started> <Process name='Process-7' pid=12468 parent=12460 started> <Process name='Process-9' pid=12470 parent=12460 started> <Process name='Process-1' pid=12462 parent=12460 started> <Process name='Process-5' pid=12466 parent=12460 started> |
Next, let’s explore what happens if all child processes terminate before we get a list of active child processes.
Overwhelmed by the python concurrency APIs?
Find relief, download my FREE Python Concurrency Mind Maps
Example of All Child Processes Finished
We can explore getting a list of active child processes after many child processes have terminated.
In this example, we can update the example from the previous section so that each child process blocks for a tenth of a second (100 milliseconds). The main process will block for longer, 300 milliseconds, and then reports on the details of all active child processes.
We expect the list of active children to be empty in this case.
The updated task() function in which child processes only block for a tenth of a second is listed below.
1 2 3 4 |
# function to execute in a new process def task(): # block for a moment sleep(0.1) |
Tying this together, the complete example is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# SuperFastPython.com # get all active child processes after the child processes have terminated from time import sleep from multiprocessing import active_children from multiprocessing import Process # function to execute in a new process def task(): # block for a moment sleep(0.1) # protect the entry point if __name__ == '__main__': # configure and start child processes for _ in range(10): # create and start child process Process(target=task).start() # wait a moment sleep(0.3) # get all active child processes children = active_children() # report details print(f'Active Children: {len(children)}') print(children) |
Running the example first configures and starts ten child processes.
The main process then blocks.
The child processes run, block for a fraction of a second then terminate.
The main process resumes, then gets a list of all active child processes.
In this case, the list is empty as all child processes that were started have since terminated.
1 2 |
Active Children: 0 [] |
Next, let’s explore the case where child processes themselves have child processes.
Example Children of Child Processes Not Included
We can explore getting active child processes when the child processes themselves have child processes.
Importantly, we expect that the multiprocessing.active_children() function to only return those child processes that belong to or were created by the current process.
This means that child processes created by children of the current process should be excluded from the list of child processes returned by the multiprocessing.active_children() function.
We can explore this by first defining a function to be executed by children of child processes. This function will block for one second.
1 2 3 4 |
# function to execute in a new process def task2(): # block for a moment sleep(1) |
Next, we can define the function to be executed by child processes of the main process.
This function will create a child process to execute our task2() function, then block for one second.
1 2 3 4 5 6 |
# function to execute in a new process def task(): # start a child process Process(target=task2).start() # block for a moment sleep(1) |
Finally, as before, the main process will start ten child processes, each configured to run our task() function.
1 2 3 4 5 |
... # configure and start child processes for _ in range(10): # create and start child process Process(target=task).start() |
The main process will block for a fraction of a second, then report the details of all currently active child processes of the main process.
1 2 3 4 5 6 7 8 9 |
... # wait a moment sleep(0.3) # get all active child processes children = active_children() # report details print(f'Active Children: {len(children)}') for child in children: print(child) |
Finally, the main process will block until all child processes have terminated.
1 2 3 4 |
... # block until all children are finished for child in children: child.join() |
Tying this together, the complete example is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# SuperFastPython.com # get all active child processes when child processes themselves have child processes from time import sleep from multiprocessing import active_children from multiprocessing import Process # function to execute in a new process def task2(): # block for a moment sleep(1) # function to execute in a new process def task(): # start a child process Process(target=task2).start() # block for a moment sleep(1) # protect the entry point if __name__ == '__main__': # configure and start child processes for _ in range(10): # create and start child process Process(target=task).start() # wait a moment sleep(0.3) # get all active child processes children = active_children() # report details print(f'Active Children: {len(children)}') for child in children: print(child) # block until all children are finished for child in children: child.join() |
Running the example first starts ten child processes in the main process.
The main process then blocks for a fraction of a second.
Each child process then creates its own child process, then blocks for one second. The new child processes themselves block for one second.
At this point there are 20 child processes running and the main process. A total of ten of the child processes belong to the main process, and the remaining ten are children of the child processes, one per child process.
The main process resumes, then gets a list of all child processes and reports their details.
In this case, we can see that there are ten active processes for the main process and that the list has excluded all active children of currently active child processes.
1 2 3 4 5 6 7 8 9 10 11 |
Active Children: 10 <Process name='Process-3' pid=12524 parent=12520 started> <Process name='Process-10' pid=12531 parent=12520 started> <Process name='Process-4' pid=12525 parent=12520 started> <Process name='Process-2' pid=12523 parent=12520 started> <Process name='Process-7' pid=12528 parent=12520 started> <Process name='Process-9' pid=12530 parent=12520 started> <Process name='Process-6' pid=12527 parent=12520 started> <Process name='Process-5' pid=12526 parent=12520 started> <Process name='Process-8' pid=12529 parent=12520 started> <Process name='Process-1' pid=12522 parent=12520 started> |
Further Reading
This section provides additional resources that you may find helpful.
Python Multiprocessing Books
- Python Multiprocessing Jump-Start, Jason Brownlee (my book!)
- Multiprocessing API Interview Questions
- Multiprocessing API Cheat Sheet
I would also recommend specific chapters in the books:
- Effective Python, Brett Slatkin, 2019.
- See: Chapter 7: Concurrency and Parallelism
- High Performance Python, Ian Ozsvald and Micha Gorelick, 2020.
- See: Chapter 9: The multiprocessing Module
- Python in a Nutshell, Alex Martelli, et al., 2017.
- See: Chapter: 14: Threads and Processes
Guides
- Python Multiprocessing: The Complete Guide
- Python Multiprocessing Pool: The Complete Guide
- Python ProcessPoolExecutor: The Complete Guide
APIs
References
Takeaways
You now know how to get child processes in Python.
Do you have any questions?
Ask your questions in the comments below and I will do my best to answer.
Photo by Abner Valero on Unsplash
Do you have any questions?