Return Code Evaluations and Assertions

๐Ÿท๏ธ Operating System and System Operations / Shell Commands with Subprocess

When your scripts run shell commands or external programs, the operating system always sends back a return code (also called exit code or status code). This small number tells you whether the command succeeded or failed. Learning to evaluate these codes properly is essential for building reliable automation that can react to failures, retry operations, or stop execution when something goes wrong.


โš™๏ธ What Is a Return Code?

Every command or program you run finishes with a numeric exit status:

  • 0 means the command completed successfully
  • Any non-zero value (1, 2, 127, etc.) indicates an error or abnormal termination

Python captures this return code automatically when you use the subprocess module. You can inspect it to decide what your script should do next.


๐Ÿ“Š Checking Return Codes with subprocess

When you run a command using subprocess.run(), the result object contains a returncode attribute:

  • Access it directly as result.returncode
  • Compare it to 0 to check for success
  • Use conditional logic to handle failures differently

A typical pattern looks like this:

  • Run the command and store the result
  • Check if result.returncode != 0
  • If non-zero, log the error or exit the script with a message
  • If zero, continue with the next step

๐Ÿ› ๏ธ Using check=True for Automatic Validation

Instead of manually checking return codes every time, you can let Python do the work by passing check=True to subprocess.run():

  • With check=True, Python raises a CalledProcessError if the return code is non-zero
  • This stops your script immediately unless you catch the exception
  • It is ideal for commands that must succeed before proceeding

Without check=True, your script continues running even if the command fails, which can lead to unpredictable behavior downstream.


๐Ÿ•ต๏ธ Understanding Common Return Codes

Different return codes give you clues about what went wrong:

Return Code Meaning Typical Cause
0 Success Command completed without errors
1 General error Command failed for a generic reason
2 Misuse of shell builtins Invalid syntax or wrong arguments
126 Command not executable Permission denied or file is not executable
127 Command not found The program does not exist in the system PATH
130 Script terminated by Ctrl+C User interrupted the process
137 Killed by SIGKILL Process was forcefully terminated
255 Exit status out of range Command returned a value outside 0โ€“255

โœ… Introduction to Assertions

Assertions are a lightweight way to enforce conditions in your code. The assert statement checks if a condition is True, and if it is False, it raises an AssertionError and stops execution.

Use assertions for:

  • Validating that a return code is zero
  • Confirming that a file exists before reading it
  • Checking that variables have expected values
  • Testing assumptions during development

The syntax is simple: assert condition, "optional error message"


๐Ÿงช Combining Return Codes with Assertions

You can combine both concepts to create self-checking scripts:

  • Run a command and capture the result
  • Use assert result.returncode == 0, "Command failed with code: {result.returncode}"
  • If the command fails, the script stops with a clear message
  • If it succeeds, execution continues normally

This approach is especially useful for:

  • Deployment scripts where every step must succeed
  • Testing pipelines that verify system states
  • Automation tasks that should not proceed after a failure

โš ๏ธ When to Use Assertions vs. Exceptions

Both techniques help you handle failures, but they serve different purposes:

Feature Assertions Exceptions (try/except)
Primary use Development and debugging Production error handling
Can be disabled Yes, with -O flag No, always active
Error message Custom message in assert Full exception object with traceback
Recovery Not intended for recovery Can catch and continue
Best for Checking invariants and assumptions Handling expected runtime errors

Use assertions for conditions that should never happen if your code is correct. Use exceptions for errors you anticipate and want to handle gracefully.


๐Ÿ”„ Best Practices for Return Code Evaluation

Follow these guidelines to write robust scripts:

  • Always check return codes after running external commands
  • Use check=True for commands that are critical to your workflow
  • Log the return code and command output when a failure occurs
  • Do not assume a command succeeded just because no exception was raised
  • Use meaningful exit codes in your own scripts (0 for success, 1 for general errors)
  • Document what each non-zero return code means in your code comments

๐Ÿง  Summary

Return codes are the operating system's way of telling you whether a command worked. Python's subprocess module gives you full access to these codes, and you can evaluate them manually or automatically with check=True. Assertions provide a simple way to enforce conditions and catch problems early during development. Together, these tools help you build scripts that fail fast, fail clearly, and never silently ignore errors.


Return code evaluations and assertions check whether a shell command succeeded or failed by examining its exit status.


โœ… Example 1: Checking a successful command's return code

This example runs a simple command and prints its return code to show that success equals zero.

import subprocess

result = subprocess.run(["echo", "hello"])
print(result.returncode)

๐Ÿ“ค Output: 0


โŒ Example 2: Checking a failed command's return code

This example runs a command that does not exist and prints the non-zero return code.

import subprocess

result = subprocess.run(["nonexistent_command"], capture_output=True)
print(result.returncode)

๐Ÿ“ค Output: 127


โœ… Example 3: Using check=True to raise an exception on failure

This example shows how to let Python automatically raise an error when a command fails.

import subprocess

try:
    subprocess.run(["false"], check=True)
except subprocess.CalledProcessError as error:
    print("Command failed with return code:", error.returncode)

๐Ÿ“ค Output: Command failed with return code: 1


โœ… Example 4: Using assert to validate a command succeeded

This example uses an assertion to verify that a command ran successfully before continuing.

import subprocess

result = subprocess.run(["ls", "/tmp"], capture_output=True)
assert result.returncode == 0, "ls command failed"
print("Command succeeded")

๐Ÿ“ค Output: Command succeeded


โœ… Example 5: Practical pattern โ€” run command and assert success

This example runs a real-world command and uses assert to confirm it completed without errors.

import subprocess

result = subprocess.run(["mkdir", "-p", "/tmp/test_folder"], capture_output=True)
assert result.returncode == 0, f"mkdir failed with code {result.returncode}"
print("Folder created successfully")

๐Ÿ“ค Output: Folder created successfully


Comparison Table

Method Behavior on Success Behavior on Failure Use Case
result.returncode Returns 0 Returns non-zero integer Manual checking
check=True Continues execution Raises CalledProcessError Automatic error handling
assert result.returncode == 0 Continues execution Raises AssertionError Validation in tests or scripts

When your scripts run shell commands or external programs, the operating system always sends back a return code (also called exit code or status code). This small number tells you whether the command succeeded or failed. Learning to evaluate these codes properly is essential for building reliable automation that can react to failures, retry operations, or stop execution when something goes wrong.


โš™๏ธ What Is a Return Code?

Every command or program you run finishes with a numeric exit status:

  • 0 means the command completed successfully
  • Any non-zero value (1, 2, 127, etc.) indicates an error or abnormal termination

Python captures this return code automatically when you use the subprocess module. You can inspect it to decide what your script should do next.


๐Ÿ“Š Checking Return Codes with subprocess

When you run a command using subprocess.run(), the result object contains a returncode attribute:

  • Access it directly as result.returncode
  • Compare it to 0 to check for success
  • Use conditional logic to handle failures differently

A typical pattern looks like this:

  • Run the command and store the result
  • Check if result.returncode != 0
  • If non-zero, log the error or exit the script with a message
  • If zero, continue with the next step

๐Ÿ› ๏ธ Using check=True for Automatic Validation

Instead of manually checking return codes every time, you can let Python do the work by passing check=True to subprocess.run():

  • With check=True, Python raises a CalledProcessError if the return code is non-zero
  • This stops your script immediately unless you catch the exception
  • It is ideal for commands that must succeed before proceeding

Without check=True, your script continues running even if the command fails, which can lead to unpredictable behavior downstream.


๐Ÿ•ต๏ธ Understanding Common Return Codes

Different return codes give you clues about what went wrong:

Return Code Meaning Typical Cause
0 Success Command completed without errors
1 General error Command failed for a generic reason
2 Misuse of shell builtins Invalid syntax or wrong arguments
126 Command not executable Permission denied or file is not executable
127 Command not found The program does not exist in the system PATH
130 Script terminated by Ctrl+C User interrupted the process
137 Killed by SIGKILL Process was forcefully terminated
255 Exit status out of range Command returned a value outside 0โ€“255

โœ… Introduction to Assertions

Assertions are a lightweight way to enforce conditions in your code. The assert statement checks if a condition is True, and if it is False, it raises an AssertionError and stops execution.

Use assertions for:

  • Validating that a return code is zero
  • Confirming that a file exists before reading it
  • Checking that variables have expected values
  • Testing assumptions during development

The syntax is simple: assert condition, "optional error message"


๐Ÿงช Combining Return Codes with Assertions

You can combine both concepts to create self-checking scripts:

  • Run a command and capture the result
  • Use assert result.returncode == 0, "Command failed with code: {result.returncode}"
  • If the command fails, the script stops with a clear message
  • If it succeeds, execution continues normally

This approach is especially useful for:

  • Deployment scripts where every step must succeed
  • Testing pipelines that verify system states
  • Automation tasks that should not proceed after a failure

โš ๏ธ When to Use Assertions vs. Exceptions

Both techniques help you handle failures, but they serve different purposes:

Feature Assertions Exceptions (try/except)
Primary use Development and debugging Production error handling
Can be disabled Yes, with -O flag No, always active
Error message Custom message in assert Full exception object with traceback
Recovery Not intended for recovery Can catch and continue
Best for Checking invariants and assumptions Handling expected runtime errors

Use assertions for conditions that should never happen if your code is correct. Use exceptions for errors you anticipate and want to handle gracefully.


๐Ÿ”„ Best Practices for Return Code Evaluation

Follow these guidelines to write robust scripts:

  • Always check return codes after running external commands
  • Use check=True for commands that are critical to your workflow
  • Log the return code and command output when a failure occurs
  • Do not assume a command succeeded just because no exception was raised
  • Use meaningful exit codes in your own scripts (0 for success, 1 for general errors)
  • Document what each non-zero return code means in your code comments

๐Ÿง  Summary

Return codes are the operating system's way of telling you whether a command worked. Python's subprocess module gives you full access to these codes, and you can evaluate them manually or automatically with check=True. Assertions provide a simple way to enforce conditions and catch problems early during development. Together, these tools help you build scripts that fail fast, fail clearly, and never silently ignore errors.

Interactive Views

You are currently in ๐Ÿ“š All-in-One mode. Use the tabs at the top to switch to ๐Ÿ“– Theory Only or ๐Ÿ’ป Code Only views.

Return code evaluations and assertions check whether a shell command succeeded or failed by examining its exit status.


โœ… Example 1: Checking a successful command's return code

This example runs a simple command and prints its return code to show that success equals zero.

import subprocess

result = subprocess.run(["echo", "hello"])
print(result.returncode)

๐Ÿ“ค Output: 0


โŒ Example 2: Checking a failed command's return code

This example runs a command that does not exist and prints the non-zero return code.

import subprocess

result = subprocess.run(["nonexistent_command"], capture_output=True)
print(result.returncode)

๐Ÿ“ค Output: 127


โœ… Example 3: Using check=True to raise an exception on failure

This example shows how to let Python automatically raise an error when a command fails.

import subprocess

try:
    subprocess.run(["false"], check=True)
except subprocess.CalledProcessError as error:
    print("Command failed with return code:", error.returncode)

๐Ÿ“ค Output: Command failed with return code: 1


โœ… Example 4: Using assert to validate a command succeeded

This example uses an assertion to verify that a command ran successfully before continuing.

import subprocess

result = subprocess.run(["ls", "/tmp"], capture_output=True)
assert result.returncode == 0, "ls command failed"
print("Command succeeded")

๐Ÿ“ค Output: Command succeeded


โœ… Example 5: Practical pattern โ€” run command and assert success

This example runs a real-world command and uses assert to confirm it completed without errors.

import subprocess

result = subprocess.run(["mkdir", "-p", "/tmp/test_folder"], capture_output=True)
assert result.returncode == 0, f"mkdir failed with code {result.returncode}"
print("Folder created successfully")

๐Ÿ“ค Output: Folder created successfully


Comparison Table

Method Behavior on Success Behavior on Failure Use Case
result.returncode Returns 0 Returns non-zero integer Manual checking
check=True Continues execution Raises CalledProcessError Automatic error handling
assert result.returncode == 0 Continues execution Raises AssertionError Validation in tests or scripts