How to Run External Programs in Python 3 with Subprocess

Avatar

By squashlabs, Last Updated: Oct. 18, 2023

How to Run External Programs in Python 3 with Subprocess

Introduction to Running External Programs

Running external programs from within a Python script can be a very useful capability, enabling you to leverage existing tools and utilities to enhance the functionality of your code. In this chapter, we will explore how to use the subprocess module in Python 3 to execute external programs. We will cover the basics of running external programs, including how to pass arguments, capture output, and handle errors.

Related Article: Handling Large Volumes of Data in FastAPI

Code Snippet: Running a Simple External Program

To run an external program in Python using the subprocess module, we can use the subprocess.run() function. This function takes a list of strings as its first argument, where the first element is the name or path of the program, and the remaining elements are the command-line arguments.

import subprocess

result = subprocess.run(["ls", "-l"])

In the example above, we use the ls command with the -l option to list the files and directories in the current directory. The subprocess.run() function runs the command and returns a CompletedProcess object, which contains information about the executed process, such as the return code.

Code Snippet: Reading Output from a Subprocess

In addition to running an external program, we often need to capture its output for further processing. The subprocess.run() function provides an easy way to do this using the stdout parameter. By setting stdout to subprocess.PIPE, we can capture the output of the subprocess as a byte string, which can then be decoded to a string for further manipulation.

import subprocess

result = subprocess.run(["echo", "Hello, World!"], stdout=subprocess.PIPE)
output = result.stdout.decode("utf-8")

print(output)  # Output: Hello, World!

In the above example, we use the echo command to print "Hello, World!" to the standard output. By setting stdout=subprocess.PIPE, the output of the command is captured and stored in the stdout attribute of the CompletedProcess object. We then decode the byte string to a UTF-8 string using the decode() method.

Overview of the Subprocess Module

The subprocess module in Python provides a powerful and flexible way to run external programs and interact with them. It offers several functions and classes that allow you to control various aspects of the execution, such as input and output redirection, error handling, and process management. In this chapter, we will provide an overview of the subprocess module and its key components.

Related Article: How to Join Sequences in Python

Code Snippet: Using subprocess.run with Shell Commands

One of the simplest ways to use the subprocess module is by running shell commands. The subprocess.run() function allows you to execute shell commands by passing a single string as the command argument.

import subprocess

result = subprocess.run("echo Hello, World!", shell=True)

In the above example, we use the echo command to print "Hello, World!" to the standard output. By setting shell=True, the command is executed in a shell environment, allowing us to use shell-specific syntax and features.

Code Snippet: Using subprocess.run with Timeout

Sometimes, it is necessary to set a timeout for the execution of an external program to prevent it from running indefinitely. The subprocess.run() function allows you to specify a timeout value using the timeout parameter.

import subprocess

try:
    result = subprocess.run(["sleep", "5"], timeout=3)
except subprocess.TimeoutExpired:
    print("Timeout expired!")

In the above example, we use the sleep command to pause the execution for 5 seconds. However, we set the timeout to 3 seconds. Since the sleep command takes longer than the specified timeout, a TimeoutExpired exception is raised, and we handle it accordingly.

Basic Functions and Their Usage

The subprocess module provides several functions and classes for running external programs. In this chapter, we will explore the basic functions of the subprocess module and their usage. We will cover functions such as subprocess.run(), subprocess.call(), and subprocess.check_output(), and discuss when and how to use them effectively.

Code Snippet: Running a Simple External Program

To run an external program, the subprocess.run() function is a recommended choice. It provides a high-level interface for executing external programs and capturing their output.

import subprocess

result = subprocess.run(["ls", "-l"])

In the above example, we use the ls command with the -l option to list the files and directories in the current directory. The subprocess.run() function runs the command and returns a CompletedProcess object, which contains information about the executed process, such as the return code.

Related Article: How to Delete a Column from a Pandas Dataframe

Code Snippet: Error Handling in Subprocess

Error handling is an essential aspect of running external programs. The subprocess module provides ways to handle errors, such as non-zero return codes or exceptions raised during execution.

import subprocess

try:
    result = subprocess.run(["invalid_command"])
except subprocess.CalledProcessError as e:
    print(f"Command failed with return code {e.returncode}")

In the above example, we intentionally run an invalid command to trigger a CalledProcessError. This exception is raised when a subprocess returns a non-zero return code, indicating an error. We can access the return code using the returncode attribute of the exception object.

Exploring subprocess.run Function

The subprocess.run() function is a versatile and commonly used function in the subprocess module. It provides a high-level interface for running external programs and capturing their output. In this chapter, we will explore the various parameters and options available with the subprocess.run() function, and how to use them effectively.

Code Snippet: Running a Simple External Program

To run a simple external program, we can use the subprocess.run() function with the program name and its command-line arguments as a list of strings.

import subprocess

result = subprocess.run(["ls", "-l"])

In the example above, we use the ls command with the -l option to list the files and directories in the current directory. The subprocess.run() function runs the command and returns a CompletedProcess object, which contains information about the executed process, such as the return code.

Code Snippet: Using subprocess.run with Shell Commands

The subprocess.run() function also allows us to run shell commands directly by passing a single string as the command argument.

import subprocess

result = subprocess.run("echo Hello, World!", shell=True)

In the above example, we use the echo command to print "Hello, World!" to the standard output. By setting shell=True, the command is executed in a shell environment, allowing us to use shell-specific syntax and features.

Related Article: How To Use Ternary Operator In Python

Common Use Cases of subprocess.run

The subprocess module in Python provides a wide range of capabilities for running external programs. In this chapter, we will explore some common use cases of the subprocess.run() function and how to handle them effectively. We will cover scenarios such as passing command-line arguments, capturing output, and handling errors.

Code Snippet: Running a Program with Command-Line Arguments

To run a program with command-line arguments, we can pass them as a list of strings to the subprocess.run() function.

import subprocess

result = subprocess.run(["python", "script.py", "--arg1", "value1", "--arg2", "value2"])

In the above example, we run a Python script named script.py with two command-line arguments --arg1 and --arg2, along with their respective values. The subprocess.run() function executes the script with the provided arguments.

Code Snippet: Capturing Output from a Subprocess

To capture the output of a subprocess, we can set the stdout parameter of the subprocess.run() function to subprocess.PIPE.

import subprocess

result = subprocess.run(["echo", "Hello, World!"], stdout=subprocess.PIPE)
output = result.stdout.decode("utf-8")

print(output)  # Output: Hello, World!

In the above example, we use the echo command to print "Hello, World!" to the standard output. By setting stdout=subprocess.PIPE, the output of the command is captured and stored in the stdout attribute of the CompletedProcess object. We then decode the byte string to a UTF-8 string using the decode() method.

Best Practices When Using subprocess.run

When using the subprocess.run() function to run external programs in Python, it is important to follow best practices to ensure the security and efficiency of your code. In this chapter, we will discuss some best practices to consider when using the subprocess.run() function, including input validation, proper handling of command-line arguments, and handling of sensitive data.

Related Article: How To Get Current Directory And Files Directory In Python

Code Snippet: Validating User Input for External Programs

When passing user input as command-line arguments to external programs, it is crucial to validate and sanitize the input to prevent security vulnerabilities such as command injection.

import subprocess

user_input = input("Enter a filename: ")

# Validate the user input
if not user_input.isalnum():
    raise ValueError("Invalid input")

# Run the external program
result = subprocess.run(["ls", user_input])

In the above example, we prompt the user to enter a filename and validate the input using the isalnum() method. If the input contains non-alphanumeric characters, we raise a ValueError to indicate invalid input. This validation helps prevent command injection attacks.

Code Snippet: Handling Command-Line Arguments Safely

When passing command-line arguments to external programs, it is important to properly handle special characters and escape sequences to prevent unintended behavior.

import subprocess
import shlex

filename = "file with spaces.txt"

# Create the command with properly escaped arguments
command = f"ls {shlex.quote(filename)}"

# Run the external program
result = subprocess.run(command, shell=True)

In the above example, we have a filename that contains spaces. To ensure that the filename is properly handled as a command-line argument, we use the shlex.quote() function to escape any special characters or escape sequences. This helps prevent issues with filenames containing spaces or other special characters.

Real World Example: Using subprocess.run in Web Scraping

Web scraping is a common use case for running external programs in Python. In this chapter, we will explore a real-world example of using the subprocess.run() function in web scraping to interact with a headless web browser and extract data from web pages. We will cover the setup and usage of the external program, as well as handling the output and errors.

Code Snippet: Running a Headless Web Browser

To run a headless web browser for web scraping purposes, we can use a program such as Selenium WebDriver. The subprocess.run() function allows us to execute the external program and interact with it.

import subprocess

# Run the headless web browser program
result = subprocess.run(["chrome.exe", "--headless", "--disable-gpu", "http://example.com"])

# Handle the output or errors
if result.returncode == 0:
    print("Success")
else:
    print("Error")

In the above example, we run a headless web browser program (in this case, Chrome) with the specified command-line arguments. The subprocess.run() function executes the program and returns a CompletedProcess object. We can then handle the output or errors based on the return code.

Related Article: How to Adjust Font Size in a Matplotlib Plot

Performance Considerations: subprocess.run vs os.system

When running external programs in Python, it is important to consider the performance implications of different approaches. In this chapter, we will compare the performance of the subprocess.run() function with the os.system() function, and discuss the advantages and disadvantages of each approach.

Code Snippet: Running an External Program with subprocess.run

To run an external program using the subprocess.run() function, we can pass the program name and command-line arguments as a list of strings.

import subprocess

result = subprocess.run(["ls", "-l"])

In the above example, we use the ls command with the -l option to list the files and directories in the current directory. The subprocess.run() function runs the command and returns a CompletedProcess object, which contains information about the executed process, such as the return code.

Code Snippet: Running an External Program with os.system

The os.system() function provides a simple way to run an external program in Python. It takes a single string argument representing the command to be executed.

import os

result = os.system("ls -l")

In the above example, we use the ls command with the -l option to list the files and directories in the current directory. The os.system() function runs the command and returns the exit status of the command.

Advanced Techniques: Creating Pipes

In addition to running external programs, the subprocess module in Python allows for more advanced techniques, such as creating pipes for inter-process communication. In this chapter, we will explore how to create pipes using the subprocess module and how to use them to communicate between processes.

Related Article: How to Use Named Tuples in Python

Code Snippet: Creating a Pipe

To create a pipe for inter-process communication, we can use the subprocess.Popen() class and its stdout and stdin parameters.

import subprocess

# Create the parent and child processes
parent = subprocess.Popen(["echo", "Hello, World!"], stdout=subprocess.PIPE)
child = subprocess.Popen(["grep", "Hello"], stdin=parent.stdout, stdout=subprocess.PIPE)

# Get the output from the child process
output = child.communicate()[0]

print(output.decode("utf-8"))  # Output: Hello, World!

In the above example, we create a parent process that runs the echo command to print "Hello, World!" to the standard output. We then create a child process that runs the grep command to search for the string "Hello" in the input received from the parent process. The stdout of the parent process is connected to the stdin of the child process using the pipe. Finally, we retrieve and print the output from the child process.

Advanced Techniques: Using subprocess.Popen Class

The subprocess.Popen class provides a more flexible and low-level way to run external programs and interact with them. In this chapter, we will explore the usage of the subprocess.Popen class and its key methods and attributes. We will cover scenarios such as running programs in the background, redirecting input and output, and managing child processes.

Code Snippet: Running an External Program in the Background

To run an external program in the background, we can use the subprocess.Popen class and its communicate() method.

import subprocess

# Run the external program in the background
process = subprocess.Popen(["python", "script.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

# Wait for the program to finish and get the output
output, error = process.communicate()

print(output.decode("utf-8"))  # Output: Program output

In the above example, we use the subprocess.Popen class to run a Python script named script.py. By setting the stdout parameter to subprocess.PIPE, we capture the output of the program. The communicate() method waits for the program to finish and returns the output as a byte string, which we then decode to a UTF-8 string.

Error Handling Strategies

When running external programs in Python, it is important to handle errors effectively to ensure the reliability and stability of your code. In this chapter, we will discuss various error handling strategies when using the subprocess module, including handling non-zero return codes, handling exceptions, and logging errors.

Related Article: How To Check If a File Exists In Python

Code Snippet: Handling Non-Zero Return Codes

When running an external program using the subprocess.run() function, it is important to handle non-zero return codes, which indicate an error or abnormal termination of the program.

import subprocess

result = subprocess.run(["ls", "nonexistent_directory"])

if result.returncode != 0:
    print("Command failed!")

In the above example, we intentionally run the ls command on a nonexistent directory to trigger a non-zero return code. We check the return code using the returncode attribute of the CompletedProcess object and handle the error accordingly.

Code Snippet: Handling Exceptions

In addition to non-zero return codes, the subprocess module can raise exceptions in certain situations, such as when a subprocess times out or encounters an error during execution.

import subprocess

try:
    result = subprocess.run(["invalid_command"])
except subprocess.CalledProcessError as e:
    print(f"Command failed with return code {e.returncode}")

In the above example, we intentionally run an invalid command to trigger a CalledProcessError. This exception is raised when a subprocess returns a non-zero return code, indicating an error. We can access the return code using the returncode attribute of the exception object and handle the error accordingly.

These are just a few examples of error handling strategies when using the subprocess module. It is important to carefully consider the specific requirements and constraints of your application and choose the appropriate error handling approach.

More Articles from the Python Tutorial: From Basics to Advanced Concepts series:

How to Use Global Variables in a Python Function

Guide on how to use global variables within a function in Python. Learn about declaring and accessing global variables, modifying them, best practice… read more

How to Use Pandas Groupby for Group Statistics in Python

Pandas Groupby is a powerful tool in Python for obtaining group statistics. In this article, you will learn how to use Pandas Groupby to calculate co… read more

How to Pretty Print Nested Dictionaries in Python

Learn how to pretty print nested dictionaries in Python using simple steps. Discover how the pprint module and json module can help you achieve clean… read more

Converting Integer Scalar Arrays To Scalar Index In Python

Convert integer scalar arrays to scalar index in Python to avoid the 'TypeError: Only integer scalar arrays can be converted to a scalar index with 1… read more

Structuring Data for Time Series Analysis with Python

Structuring data for time series analysis in Python is essential for accurate and meaningful insights. This article provides a concise guide on the c… read more

How to Use Regex to Match Any Character in Python

Python's regex is a powerful tool for matching any character in a string. This step-by-step guide will show you how to use the Dot Metacharacter to m… read more

How to Remove a Key from a Python Dictionary

Removing a key from a Python dictionary is a common task in programming. This guide provides step-by-step instructions on how to achieve this using t… read more

Advanced Django Admin Interface: Custom Views, Actions & Security

Learn to customize the Django Admin Interface with advanced ModelAdmin customizations, custom views and actions, and enhanced security. Dive into the… read more

How to Install Specific Package Versions With Pip in Python

Guide on installing a specific version of a Python package using pip. Learn different methods such as using the == operator, specifying version range… read more

How To Read JSON From a File In Python

Reading JSON data from a file in Python is a common task for many developers. In this tutorial, you will learn different methods to read JSON from a … read more