Python Exit Codes

Sys.exit() allows you to set an exit code for a process and the exit code attribute on the multiprocessing.Process class will enable you to access the exit code. In this article, you will learn how to get and set exit codes for processes in Python.

Why Process Exit Codes?

An active instance of computer software is known as a process. In a Process, a fresh instance of the Python interpreter, every Python program is run. One thread, known as the MainThread, is used by this process, which goes by the moniker MainProcess, to carry out the program’s instructions. The underlying operating system creates and controls both processes and threads.

In order to run code concurrently, we sometimes may need to establish new child processes in our application. Python offers the ability to manage multiple processes simultaneously using class multiprocessing.Process. In addition, in multiprocessing, we might need to let other processes know whether a task carried out by a child process succeeded or failed. As a result, exit codes are used to do this.

Python Exit Codes: How to Use Them

When a process is finished, it can communicate with other processes via an exit code or exit status to let them know if it was completed successfully or not.

When a child process or callee completes the execution of a particular procedure or delegated task, it passes a tiny number to the parent process or caller, which is known as the caller’s exit status. An exit code typically has an integer value to indicate if the procedure was successful or unsuccessful, but it can also have a string message attached.

Let’s look more closely at the setting of exit codes in processes and the checking of exit codes in procedures by other processes.

Setting an Exit Code

A process can intentionally or automatically establish the exit code. For instance, the exit code will be set to zero if the process ends normally. The exit code would be set to one if the process ended due to an error or other exception. Additionally, it can set its exit code if a process actively exits.

Calling sys.exit() and supplying the exit code as a parameter will do this. As a matter of fact, the sys.exit() function causes the current process to raise a SystemExit exception, which causes the process to end. For example, the optional argument arg may be another kind of object or an integer indicating the exit status defaulting to zero.

This function assumes that the SystemExit exception is not handled and must be invoked from the process’ main thread. A successful exit is indicated by an argument value of 0. For instance:

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>...
# illustrating a successful exit
sys.exit(0)
</pre>
</div>

There is no need to provide the following because it takes on the argument’s default value.

 

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>...
# default successful exit
sys.exit()</pre>
</div>

A successful exit will likewise be considered to have been made if None is supplied as an argument. For instance:

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre># None passed as an argument is acceptable as a successful exit
sys.exit(None)</pre>
</div>

On the other hand, an unsuccessful exit is indicated by a positive integer number, often one. For instance:

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>...
# positive integer indicating an unsuccessful exit
sys.exit(1)</pre>
</div>

An alternative is to supply a string message as an argument. The message will be reported on stderr and interpreted as an unsuccessful exit, for example, a value of one. For instance:

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>...
# representing an unsuccessful exit using string
sys.exit(' use any text for unsuccessful exit')</pre>
</div>

Finding an Exit Code

Through the “exitcode” characteristic of the multiprocessing.Process, another process can obtain the exit code of a given process. For instance:

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>...
# fetching the exit code
code = process.exitcode</pre>
</div>

Therefore, a multiprocessing.Process is necessary. When creating the child process, for instance, we can hold onto the process instance. The value is set by the process executing sys.exit() or automatically depending on whether the process finished successfully or with an error is contained in the exitcode attribute.

The exit code will be 0 if the child’s execute() method produces a successful result. On the other hand, the exit code will be N if it was terminated using the sys.exit() method with the integer input N. The exitcode value will be None if the process hasn’t yet ended. Otherwise, it won’t be set.

Values of Common Exit Codes

Exit codes relevant to the application may be set for a process. The latter enables processes to exchange information about their precise exit status. Additionally, other exit code values are frequently utilized.

The integer value, for instance, is usually between 0-255, and numbers 0-127 may be set aside for frequent errors or situations. If it is an integer, shells and the like treat zero as “successful termination” and any nonzero value as “abnormal termination.” Most systems return undefinable results if it is not in the range 0-127.

Examples include:

  • 0, None: Success
  • 1: Error
  • 2: These are syntax errors on the command line
  • 120: Errors that occur when cleanup of processes happens.
  • 255: Is triggered when the exit code is outside the range.

A negative exit code might be issued if a process was terminated via a particular signal. Additionally, the exit code would be the negative number -N if its termination were by signal N. Let’s look at some worked instances now that we know how to obtain and modify an exit code for a process.

Exit Codes: Why are they explicit?

Examples of explicitly specifying an exit code while ending a process are given in this section. A successful exit code example involves a child process where we can investigate creating a successful exit code. This example will create a child process to exit a custom function. After one second of blocking, the child process will explicitly quit with a successful exit code.

We can start by defining the function that will run in the child function. After a brief period of inactivity, the function calls the sys.exit() function with a zero argument to signify a successful exit. It is done through the code_task() method, which is below.

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre># function that was run within a child process
def code_task():
    # block the code from running for 1 second
    sleep(1)
    # illustration of a successful exit
    exit(0)</pre>
</div>

We will next set up a new process instance to carry out our code_task() method within the primary process.

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>...
# A new process configuration
child = Process(target=code_task)</pre>
</div>

As soon as the process is launched, it blocks till the child process completes.

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>...
# starting the child process
child.start()
# waiting for the child process to complete
child.join()
</pre>
</div>

The primary process then gets the child process’ exit code and reports the value.

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>...
# Verify the child process's exit code.
code = child.exitcode
print(f'Child exit code: {code}')</pre>
</div>

To tie all of this together, the complete example is provided below.

 

Example: A successful exit code

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>from time import sleep
from multiprocessing import Process
from sys import exit

# function executed in a child process
def code_task():
    # block for a moment
    sleep(1)
    # exit successfully
    exit(0)

# protect the entry point
if __name__ == '__main__':
    # new process configuration
    child = Process(target=code_task)
    # starting of process belonging to the child
    child.start()
    # waiting for the process belonging to the child to complete
    child.join()
    # checking for the exit code belonging to the child process
    code = child.exitcode
    print(f'Child exit code: {code}')</pre>
</div>

The child process is created and launched by running the example first. Once the child process has ended, the primary process becomes blocked. Further, the child process sleeps for one second before successfully exiting with the exit code zero.

The child process ends, and the primary process keeps running. It reports the value after obtaining the exit code from the child process. In this instance, we can see that it has the value zero we specified when invoking exit() in the child process.

An example of a failed exit code

In this section, we will investigate a failed exit code. Remember that a value other than zero denotes a failure of the process. As a matter of fact, the example from the preceding section can be changed so that the process calls exit() with the value one.

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>...
# demonstrating an unsuccessful exit
exit(1)</pre>
</div>

The modified code_task() method is shown in the list below.

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre># the execution of the following function occurs in a child's process
def code_task():
    # let it sleep for 1 second
    sleep(1)
    # demo of unsuccessful exit
    exit(1)</pre>
</div>

To tie all of this together, the entire example is provided below.

Example: Unsuccessful exit code demonstration

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>from time import sleep
from multiprocessing import Process
from sys import exit
 
# execution of the function happens in a child process
def code_task():
    # let it sleep for 1 second
    sleep(1)
    # illustrating the unsuccessful exit
    exit(1)
 
# entry's point protection
if __name__ == '__main__':
    # new process configuration
    child = Process(target=code_task)

    # child process commencement
    child.start()
    # waiting for the process belonging to the child to complete
    child.join()
    # confirming the child processes' exit code
    code = child.exitcode
    print(f'Child exit code: {code}')</pre>
</div>

The child process is created and launched by running the example first. Once the child process has ended, the primary process becomes blocked. The child process sleeps for one second before attempting an unsuccessful departure with an exit code of 1.

The child process ends, and the primary process keeps running. It reports the value after obtaining the exit code from the child process. When we call exit() in this instance, we can see that it has the value set in the child process.

A sample exit code for an error message

The possibility of using a string message as an exit code is open. Remember that if you set a string message as an exit code and report the string message on standard error, it means that the exit failed (stderr). By executing sys.exit(), the above example can be updated to set a string message.

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>...
# failure to quit with a message
exit('unsuccessful exit with a message)</pre>
</div>

The modified code_task() method is shown in the list below.

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre># function that was run within a child process
def code_task():
    # let it sleep for 1 second
    sleep(1)
    # failure to quit with a message
    exit('unsuccessful quit with a message)</pre>
</div>

To tie all of this together, the complete example is provided below.

Example: An unsuccessful message from the exit code

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>from time import sleep
from multiprocessing import Process
from sys import exit
 
# the execution of this function is within  a child process
def code_task():
    # let it sleep for 1 second
    sleep(1)
    # failure to quit with a message
    exit('unsuccessful quit with a message)
 
# protect the entry point
if __name__ == '__main__':
    # A new process configuration
    child = Process(target=code_task)
    # starting the child process
    child.start()
    # waiting for the completion of the child process
    child.join()
    # checking the child processes' exit code
    code = child.exitcode
    print(f'Child exit code: {code}')</pre>
</div>

The child process is created and launched by running the example first. Once the child process has ended, the primary process becomes blocked.Then, the child process sleeps for one second before exiting with an error-indicating string message as its exit code.

The primary process continues after the child ends and transmits the string message to standard error.

Once the exit code has been obtained from the child process, the primary process reports the value. In this instance, we can see that the message was automatically reported and that the exit code has a value of 1, which denotes a failed exit.

Automatic Exit Codes

Examples of exit codes that are automatically set when a process is terminated are given in this section.

Automatic Exit Code On Normal Exit

In this instance, we can investigate the exit code that Python processes automatically use when they terminate regularly.

Remember that when a Python process exits, the exit code is usually set to zero, signaling a successful exit. This can be done by changing the above example to eliminate the code_task() function call made in a child process’s call to sys.exit(). The modified code_task() method is shown in the list below.

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre># executing the function in a process belonging to the child
def code_task():
    # let it sleep for 1 second
    sleep(1)</pre>
</div>

To tie all of this together, the entire example is provided below.

Example: Normal successful exit for a process

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>from time import sleep
from multiprocessing import Process
from sys import exit
 
#execution of the function is in a child process
def code_task():
    # let it sleep for 1 second
    sleep(1)
 
# entry point  protection
if __name__ == '__main__':
    # new process configuration
    child = Process(target=code_task)
    # child process initiation
    child.start()
    # awaiting the completion of the child process
    child.join()
    # checking the child process for the exit code
    code = child.exitcode
    print(f'Exit code from the Child process: {code}')</pre>
</div>

The child process is created and launched by running the example first. Once the child process has ended, the primary process becomes blocked. After a brief sleep period, the child process generally terminates without using an explicit exit code.

The child process ends, and the primary process keeps running. It reports the value after obtaining the exit code from the child process. As we can see in this instance, it is set to zero automatically after the child process is terminated, usually signifying a successful exit.

Exit Code Automatically Upon Exception

In this instance, we can investigate the exit code set that is generated whenever a Python process terminates abnormally.

Remember that when a Python process exits with an exception, the exit code is set to one, denoting a failed exit. It can be done by modifying the previous example to throw an exception during the child process’s function execution.

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>...
# exception trigger
raise Exception('Encountered an obstacle)

The modified code_task() method is shown in the list below.


# execution of the function in a child process
def task():
    # let it sleep for a while
    sleep(1)
    # exception trigger
    raise Exception('Encountered an obstacle)</pre>
</div>

To tie all of this together, the whole example is provided below.

Example: Unsuccessful exit for exiting with exception

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>from time import sleep
from multiprocessing import Process
from sys import exit
 
# execution of the function in a child process
def code_task():
    # let it wait for a while
    sleep(1)
    #exception trigger
    raise Exception('Encountered an obstacle)
 
# protect the entry point
if __name__ == '__main__':
    # new process  configuration
    child = Process(target=code_task)
    # child process initiation
    child.start()
    # awaiting the completion of the child process
    child.join()
    # checking the child process exit code
    code = child.exitcode
    print(f' The exit code for the Child is: {code}')</pre>
</div>

The child process is created and launched by running the example first. Once the child process has ended, the primary process becomes blocked. After sleeping for one second, the child process ends by raising an exception.

The default way for a child process to handle an exception is to report the stack trace to standard error. The child process ends, and the primary process keeps running. It reports the value after obtaining the exit code from the child process. As we can see in this instance, it is set to zero, indicating an unsuccessful exit, which happened automatically when the child process terminated with an exception.

Python Exit Codes Using sys

Although we don’t explicitly mention these exit codes in the Python code, that doesn’t mean that Python doesn’t have them. Exit codes are a feature of all programming languages.

Python’s built-in sys module is used to implement exit codes. Additionally, the exit() method in the sys module enables us to utilize exit codes to end processes as necessary. The exit code is the only input the exit() method will take. The argument’s default value indicates a successful answer, which is 0.

<div class="wp-block-codemirror-blocks-code-block code-block">
<pre>import sys

print("Codeunderscored")
sys.exit(0)
print("Welcome to Exit Codes in Python")</pre>
</div>

Because sys.exit(0) ends the program before the interpreter could even get to the last print statement. As a result, the program above displays “Codeunderscored.” So, wherever you want to halt the application abruptly, use this statement.

Conclusion

You’ve probably heard of the term “exit code” if you’re a programmer or developer. Exit codes can be thought of as messages that programs typically send to the operating system and occasionally to other programs.

Exit codes provide feedback about a program’s success or failure to the operating system or other programs. Success is considered to have occurred when the program runs without mistake. And when an error is made, it is referred to as a failure.

Different situations require different exit strategies. Typically, we employ the exit codes 0 and 1. 1 denotes a failed execution, whereas 0 denotes a successful one.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *