Last Updated on September 12, 2022
You can call sys.exit() to exit a process.
In this tutorial you will discover how to use sys.exit() with parent and child processes in Python.
Let’s get started.
What is sys.exit()
The sys.exit() function is described as exiting the Python interpreter.
Raise a SystemExit exception, signaling an intention to exit the interpreter.
— sys — System-specific parameters and functions
When called, the sys.exit() function will raise a SystemExit exception.
This exception is (typically) not caught and bubbles up to the top of a stack of the running thread, causing it and the process to exit.
… This allows the exception to properly propagate up and cause the interpreter to exit. When it is not handled, the Python interpreter exits; no stack traceback is printed.
— Built-in Exceptions
The sys.exit() function takes an argument that indicates the success or failure of the exit status.
A value of None (the default) or zero indicates a successful , whereas a larger value indicates an unsuccessful exit.
If the value is an integer, it specifies the system exit status (passed to C’s exit() function); if it is None, the exit status is zero; if it has another type (such as a string), the object’s value is printed and the exit status is one.
— Built-in Exceptions
Importantly, finally operations in try-except-finally and try-finally patterns are executed. This allows a program to clean-up before exiting.
Cleanup actions specified by finally clauses of try statements are honored …
— sys — System-specific parameters and functions
In multiprocessing programming, we may make calls to sys.exit() to close our program.
How does sys.exit() interact with the main process and child processes in Python?
Run loops using all CPUs, download your FREE book to learn how.
sys.exit() and Exit Codes
Each Python process has an exit code.
The exit code of a process is accessible via the multiprocessing.Process.exitcode attribute.
The process exitcode is set automatically, for example:
- If the process is still running, the exitcode will be None.
- If the process exited normally, the exitcode will be 0.
- If the process terminated with an uncaught exception, the exitcode will be 1.
The exitcode can also be set via a call to sys.exit().
For example, a child process may exit with a call to sys.exit() with no arguments.
The child process will terminate and the exitcode will be set to 0.
How to Use sys.exit()
The sys.exit() function is used by simply making the function call.
A normal exit can be achieved by calling the function with no argument, e.g. defaulting to a value of None.
For example:
1 2 3 |
... # exit normally sys.exit() |
A normal exit can also be achieved by passing the value of None or 0 as an argument.
1 2 3 |
... # exit normally sys.exit(0) |
An unsuccessful exit can be signaled by passing a value other than 0 or None.
This may be an integer exit code, such as 1.
For example
1 2 3 |
... # exit with error sys.exit(1) |
Alternatively, it may be a string value that may be reported as part of the exit.
For example:
1 2 3 |
... # exit with error sys.exit('Something bad happened') |
Now that we know how to use sys.exit(), let’s look at some worked examples.
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.
Exit the Main Process
We can explore how to exit the main process using sys.exit().
In this example we will report a message, block for a moment, then exit successfully. We will also include code after the call to sys.exit() to demonstrate that indeed the program is terminated and additional code is unreachable.
The complete example is listed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# SuperFastPython.com # example of exiting the main process from time import sleep import sys # report a message print('Main process running') # block for a moment sleep(2) # exit the main process print('Exiting...') sys.exit(0) # never gets here print('Never gets here...') |
Running the example first reports a message that the main process is running.
The process then blocks for two seconds.
Once awake, the process reports a message then calls sys.exit() to exit normally. The program terminates and the final print statement is never reached.
When the sys.exit() function is called, a SystemExit exception is raised in the main thread. The main thread terminates. As there are no other threads and no child processes, the main process terminates.
1 2 |
Main process running Exiting... |
Next, let’s explore calling sys.exit() from a child process.
Overwhelmed by the python concurrency APIs?
Find relief, download my FREE Python Concurrency Mind Maps
Exit a Child Process
We can explore calling sys.exit() from a child process.
In this example we will execute a new function in a child process. The child process will report a message, block for a moment, then call exit with a value of one to indicate an unsuccessful exit. It will also include code after the call to exit to confirm that additional code is not reachable. The main process will report the status and exitcode of the child process.
First, we can define a function to execute in a child process.
The function reports a message, blocks, then exits with an exit code of one.
The task() function below implements this.
1 2 3 4 5 6 7 8 9 10 11 |
# task executed in a new process def task(): # report a message print('Child process running') # block for a moment sleep(2) # exit the child process print('Exiting...') sys.exit(1) # never gets here print('Never gets here...') |
Next, in the main process we can create a new multiprocessing.Process instance and configure it to execute our task() function.
1 2 3 |
... # create a child process child = Process(target=task) |
We can then start the process and wait for it to terminate.
1 2 3 4 5 |
... # start the child process child.start() # wait for the child process to exit child.join() |
Finally, we can check the running status of the child process to confirm it has terminated and report the exitcode.
1 2 3 4 5 |
... # check status of the child process print(f'Alive: {child.is_alive()}') # check the exitcode print(f'Exitcode: {child.exitcode}') |
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 |
# SuperFastPython.com # example of exiting a child process from time import sleep from multiprocessing import Process import sys # task executed in a new process def task(): # report a message print('Child process running') # block for a moment sleep(2) # exit the child process print('Exiting...') sys.exit(1) # never gets here print('Never gets here...') # entry point if __name__ == '__main__': # create a child process child = Process(target=task) # start the child process child.start() # wait for the child process to exit child.join() # check status of the child process print(f'Alive: {child.is_alive()}') # check the exitcode print(f'Exitcode: {child.exitcode}') |
Running the example first creates a child process configured to execute our target function.
The main process then starts the child process then blocks until it terminates.
The child process first reports a message that it is running then sleeps for two seconds. It then awakes, reports a message and calls sys.exit() with an exitcode of 1.
The child process terminates and the main process wakes up.
The status of the child process is reported indicating that it is no longer running (as expected) and that the exit code was 1, as we set when we called sys.exit().
This highlights how a child process may terminate itself and how the parent process may check the exitcode of a child process.
1 2 3 4 |
Child process running Exiting... Alive: False Exitcode: 1 |
Exit the Main Process With a Child Process
Calling sys.exit() in a parent process will not terminate the process if it has one or more running child processes.
We can explore this with a worked example.
In this example, we will first start a child process and have it block for a moment then check the running status and exit code of the parent process. The parent process will start the child process, block for a moment then attempt to terminate with a call to sys.exit(). The child process will continue running and will show that indeed the parent process is still alive, even after its call to sys.exit().
First, we can define a target task function.
The function will first report a message to indicate that it is running. It will then block for a few seconds to give time for the parent process to “exit“. It will then wake-up and get access to the multiprocessing.Process instance for the parent process via the multiprocessing.parent_process() function. Finally, the running status and exitcode of the parent process will be reported.
The task() function below implements this.
1 2 3 4 5 6 7 8 9 10 |
# function executed in a new process def task(): # report a message print('Child process running', flush=True) # wait a moment sleep(2) # check the status of the parent process parent = parent_process() print(f'Alive: {parent.is_alive()}', flush=True) print(f'Exitcode: {parent.exitcode}') |
The main process will first configure a new multiprocessing.Process instance to execute the task() function, then start the child process.
1 2 3 4 5 |
... # create a new process child = Process(target=task) # start the new process child.start() |
The main process will then block for a moment.
1 2 3 |
... # block for a moment sleep(1) |
It then attempts to terminate with a call to sys.exit().
1 2 3 4 |
... # exit the main process print('Exiting...') sys.exit() |
Finally, additional code is listed and is never reached, to confirm the main process has stopped.
1 2 3 |
... # never gets here print('Never gets here...') |
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 |
# SuperFastPython.com # example of exiting the main process while child is running from time import sleep from multiprocessing import Process from multiprocessing import parent_process import sys # function executed in a new process def task(): # report a message print('Child process running', flush=True) # wait a moment sleep(2) # check the status of the parent process parent = parent_process() print(f'Alive: {parent.is_alive()}', flush=True) print(f'Exitcode: {parent.exitcode}') # entry point if __name__ == '__main__': # create a new process child = Process(target=task) # start the new process child.start() # block for a moment sleep(1) # exit the main process print('Exiting...') sys.exit() # never gets here print('Never gets here...') |
Running the example first configures and starts the child process.
The main process then blocks for a moment then attempts to terminate with a call to sys.exit().
The child process reports a message, blocks for two seconds, then checks the status of the parent process after it has called sys.exit().
In this case, we can see that the parent process is still alive and does not have an exit code.
The call to sys.exit() in the main process terminated the main thread of the main process, but did not terminate the main process itself. The reason is because the main process will not terminate if it has one or more non-daemon child processes running, which it does in this case.
This highlights that careful attention must be paid when calling sys.exit() in parent processes that have running child processes.
1 2 3 4 |
Child process running Exiting... Alive: True Exitcode: None |
Note, the os._exit() function can be used instead of sys.exit() to forcefully exit a process.
It can be used in this case to exit the parent process and create an orphan child process.
For example:
1 2 3 4 |
... # exit the main process print('Exiting...') os._exit(os.EX_OK) |
The os._exit() function is more forceful than sys.exit() in that it will not execute finally blocks or other handlers, and will exit a process, even if it has running child processes.
Exit the process with status n, without calling cleanup handlers, flushing stdio buffers, etc.
— os — Miscellaneous operating system interfaces
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 |
# SuperFastPython.com # example of exiting the main process while child is running from time import sleep from multiprocessing import Process from multiprocessing import parent_process import os # function executed in a new process def task(): # report a message print('Child process running', flush=True) # wait a moment sleep(2) # check the status of the parent process parent = parent_process() print(f'Alive: {parent.is_alive()}', flush=True) print(f'Exitcode: {parent.exitcode}') # entry point if __name__ == '__main__': # create a new process child = Process(target=task) # start the new process child.start() # block for a moment sleep(1) # exit the main process print('Exiting...') os._exit(os.EX_OK) # never gets here print('Never gets here...') |
Running the example creates and starts the child process.
The parent process is then forcefully exited.
This leaves the child process orphaned with no running parent process.
The child process blocks, then wakes up and reports the status of its parent process.
In this case, we can see that indeed the parent process is no longer running. Importantly, we can see that the os._exit() function does not correctly set the exit code of the main process.
1 2 3 4 |
Child process running Exiting... Alive: False Exitcode: None |
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 use sys.exit() with parent and 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 Viktor Ritsvall on Unsplash
Do you have any questions?