Process Exit Codes in Python - Super Fast Python

You can set an exit code for a process via sys.exit() and retrieve the exit code via the exitcode attribute on the multiprocessing.Process class.

In this tutorial you will discover how to get and set exit codes for processes in Python.

Let’s get started.

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.

In multiprocessing, we may need to report the success or failure of a task executed by a child process to other processes.

This can be achieved using exit codes.

What are exit codes and how can we use them between processes in Python?

How to Use Exit Codes in Python

An exit code or exit status is a way for one process to share with another whether it is finished and if so whether it finished successfully or not.

The exit status of a process in computer programming is a small number passed from a child process (or callee) to a parent process (or caller) when it has finished executing a specific procedure or delegated task.

Exit status, Wikipedia.

An exit code is typically an integer value to represent success or failure of the process, but may also have an associated string message.

Let’s take a closer look at how we might set an exit code in a process and how another process might check the exit code of a process.

How to Set an Exit Code

A process can set the exit code automatically or explicitly.

For example, if the process exits normally, the exit code will be set to zero. If the process terminated with an error or exception, the exit code will be set to one.

A process can also set its exit code when explicitly exiting.

This can be achieved by calling the sys.exit() function and passing the exit code as an argument.

The sys.exit() function will raise a SystemExit exception in the current process, which will terminate the process.

The optional argument arg can be an integer giving the exit status (defaulting to zero), or another type of object.

sys — System-specific parameters and functions

This function must be called in the main thread of the process and assumes that the SystemExit exception is not handled.

An argument value of 0 indicates a successful exit.

For example:

...

# exit successfully

sys.exit(0)

This is the default value of the argument and does not need to be specified.

For example:

...

# exit successfully

sys.exit()

Passing a value of None as an argument will also be interpreted as a successful exit.

For example:

...

# exit successfully

sys.exit(None)

A positive integer value indicates an unsuccessful exit, typically a value of one.

For example:

...

# exit unsuccessfully

sys.exit(1)

Alternatively, a string message may be provided as an argument.

This will be interpreted as an unsuccessful exit, e.g. a value of one, and the message will be reported on stderr.

For example:

...

# exit unsuccessfully

sys.exit('Something bad happened')

You can learn more about the sys.exit() function in the tutorial:

How to Get An Exit Code

Another process can get the exit code of a process via the “exitcode” attribute of the multiprocessing.Process instance for the process.

For example:

...

# get the exit code

code = process.exitcode

This means that we require a multiprocessing.Process instance for the process. For example, we may hang on to the process instance when creating the child process.

The exitcode attribute contains the value set by the process calling sys.exit(), or the value set automatically if the process ended normally or with an error.

If the child’s run() method returned normally, the exit code will be 0. If it terminated via sys.exit() with an integer argument N, the exit code will be N.

multiprocessing — Process-based parallelism

If the process has not yet terminated, the exitcode value will not be set and will have the value None.

Common Exit Code Values

We may set exit codes for a process that are meaningful to the application.

This allows one process to communicate with another process regarding its specific status upon exit.

Additionally, there are also some commonly used exit code values.

For example, the integer value is typically between 0-255 and values 0-127 may be reserved for common situations or errors.

If it is an integer, zero is considered “successful termination” and any nonzero value is considered “abnormal termination” by shells and the like. Most systems require it to be in the range 0–127, and produce undefined results otherwise.

sys — System-specific parameters and functions

For example:

  • 0, None: Success
  • 1: Error
  • 2: Command line syntax errors
  • 120: Error during process cleanup.
  • 255: Exit code out of range.

A negative exit code may be assigned to a process if the process was terminated via a specific signal.

If it was terminated by signal N, the exit code will be the negative value -N.

multiprocessing — Process-based parallelism

Now that we know how to get and set exit codes for a process, let’s look at some worked examples.

Explicit Exit Codes

This section provides examples of explicitly setting an exit code when terminating a process.

Example of Successful Exit Code

We can explore setting a successful exit code in a child process.

In this example we will create a child process to exit a custom function. The child process will block for one second, and then exit with an explicitly successful exit code.

First, we can define the function to execute in the child function.

The function will sleep for a second, then call the sys.exit() function with an argument of zero to indicate a successful exit.

The task() function below implements this.

# function executed in a child process

def task():

    # block for a moment

    sleep(1)

    # exit successfully

    exit(0)

Next, in the main process, we will configure a new process instance to execute our task() function.

...

# configure a new process

child = Process(target=task)

The process is then started, and the main process blocks until the child process terminates.

...

# start the child process

child.start()

# wait for the child process to finish

child.join()

Finally, the main process retrieves the exit code for the child process and reports the value.

...

# check the exit code for the child process

code = child.exitcode

print(f'Child exit code: {code}')

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

# example of a successful exit code

from time import sleep

from multiprocessing import Process

from sys import exit

# function executed in a child process

def task():

    # block for a moment

    sleep(1)

    # exit successfully

    exit(0)

# protect the entry point

if __name__ == '__main__':

    # configure a new process

    child = Process(target=task)

    # start the child process

    child.start()

    # wait for the child process to finish

    child.join()

    # check the exit code for the child process

    code = child.exitcode

    print(f'Child exit code: {code}')

Running the example first creates and starts the child process.

The main process then blocks until the child process terminates.

The child process sleeps for one second, then exits with an exit code of zero, indicating success.

The child process terminates then the main process continues on. It retrieves the exit code from the child process and reports the value.

In this case, we can see it has the value zero that we set in the child process when calling exit().

Next, let’s look at an example of an unsuccessful exit code.

Example of Unsuccessful Exit Code

We can explore an unsuccessful exit code.

Recall that any value other than zero indicates an unsuccessful end to the process.

We can update the example from the previous section so that the process calls exit() with a value of one.

...

# exit unsuccessfully

exit(1)

The updated task() function with this change is listed below.

# function executed in a child process

def task():

    # block for a moment

    sleep(1)

    # exit unsuccessfully

    exit(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

# example of an unsuccessful exit code

from time import sleep

from multiprocessing import Process

from sys import exit

# function executed in a child process

def task():

    # block for a moment

    sleep(1)

    # exit unsuccessfully

    exit(1)

# protect the entry point

if __name__ == '__main__':

    # configure a new process

    child = Process(target=task)

    # start the child process

    child.start()

    # wait for the child process to finish

    child.join()

    # check the exit code for the child process

    code = child.exitcode

    print(f'Child exit code: {code}')

Running the example first creates and starts the child process.

The main process then blocks until the child process terminates.

The child process sleeps for one second, then exits with an exit code of one, indicating an unsuccessful exit.

The child process terminates then the main process continues on. It retrieves the exit code from the child process and reports the value.

In this case, we can see it has the value of one that we set in the child process when calling exit().

Next, let’s look at an example of an unsuccessful exit code with a message.

Example of Error Message Exit Code

We can explore setting a string message as an exit code.

Recall, setting a string message as an exit code will indicate an unsuccessful exit, setting an exit code of one and reporting the string message on standard error (stderr).

We can update the previous example to set a string message when calling sys.exit().

...

# exit unsuccessfully with a message

exit('Something bad happened')

The updated task() function with this change is listed below.

# function executed in a child process

def task():

    # block for a moment

    sleep(1)

    # exit unsuccessfully with a message

    exit('Something bad happened')

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

# example of an unsuccessful exit code message

from time import sleep

from multiprocessing import Process

from sys import exit

# function executed in a child process

def task():

    # block for a moment

    sleep(1)

    # exit unsuccessfully with a message

    exit('Something bad happened')

# protect the entry point

if __name__ == '__main__':

    # configure a new process

    child = Process(target=task)

    # start the child process

    child.start()

    # wait for the child process to finish

    child.join()

    # check the exit code for the child process

    code = child.exitcode

    print(f'Child exit code: {code}')

Running the example first creates and starts the child process.

The main process then blocks until the child process terminates.

The child process sleeps for one second, then exits with an exit code of a string message, indicating an unsuccessful exit.

The child process terminates, reports the string message to standard error, then the main process continues on.

The main process then retrieves the exit code from the child process and reports the value.

In this case, we can see that the message was reported automatically, and that the exit code has the value of one, indicating an unsuccessful exit.

Something bad happened

Child exit code: 1


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.

Learn more
 


Automatic Exit Codes

This section provides examples of automatically setting an exit code when terminating a process.

Automatic Exit Code On Normal Exit

In this case we can explore the exit code set automatically when a Python process exits normally.

Recall that the exit code is set to zero indicating a successful exit when a Python process exits normally.

We can achieve this by updating the previous example to remove the call to sys.exit() from the task() function executed in a child process.

The updated task() function with this change is listed below.

# function executed in a child process

def task():

    # block for a moment

    sleep(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

# SuperFastPython.com

# example of a normal successful exit for a process

from time import sleep

from multiprocessing import Process

from sys import exit

# function executed in a child process

def task():

    # block for a moment

    sleep(1)

# protect the entry point

if __name__ == '__main__':

    # configure a new process

    child = Process(target=task)

    # start the child process

    child.start()

    # wait for the child process to finish

    child.join()

    # check the exit code for the child process

    code = child.exitcode

    print(f'Child exit code: {code}')

Running the example first creates and starts the child process.

The main process then blocks until the child process terminates.

The child process sleeps for one second, then exits normally with no explicit exit code

The child process terminates then the main process continues on. It retrieves the exit code from the child process and reports the value.

In this case, we can see it has the value zero indicating a successful exit was set automatically when the child process exited normally.

Automatic Exit Code On Exception

In this case we can explore the exit code set automatically when a Python process exits with an exception.

Recall that the exit code is set to one indicating an unsuccessful exit when a Python process exits with an exception.

We can achieve this by updating the previous example to raise an exception in the function executed by the child process.

...

# raise an exception

raise Exception('Something bad happened')

The updated task() function with this change is listed below.

# function executed in a child process

def task():

    # block for a moment

    sleep(1)

    # raise an exception

    raise Exception('Something bad happened')

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

# example of a unsuccessful exit for exiting with exception

from time import sleep

from multiprocessing import Process

from sys import exit

# function executed in a child process

def task():

    # block for a moment

    sleep(1)

    # raise an exception

    raise Exception('Something bad happened')

# protect the entry point

if __name__ == '__main__':

    # configure a new process

    child = Process(target=task)

    # start the child process

    child.start()

    # wait for the child process to finish

    child.join()

    # check the exit code for the child process

    code = child.exitcode

    print(f'Child exit code: {code}')

Running the example first creates and starts the child process.

The main process then blocks until the child process terminates.

The child process sleeps for one second, then exits by raising an exception.

The exception stack trace is reported to standard error, the default behavior for handling an exception in a child process

The child process terminates then the main process continues on. It retrieves the exit code from the child process and reports the value.

In this case, we can see it has the value zero indicating an unsuccessful exit was set automatically when the child process exited with an exception.

Process Process-1:

Traceback (most recent call last):

  ...

Exception: Something bad happened

Child exit code: 1

Further Reading

This section provides additional resources that you may find helpful.

Python Multiprocessing Books

I would also recommend specific chapters in the books:

Guides

APIs

References


    Python Multiprocessing Jump-Start

    Loving The Tutorials?

    Why not take the next step? Get the book.

    Learn more
     


    Takeaways

    You now know how to get and set exit codes for 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 David Maginley on Unsplash