Of course! Let's dive into easyprocess, a Python library that makes running external command-line programs incredibly simple.

What is easyprocess?
easyprocess is a third-party Python library designed to be a "wrapper" around Python's standard subprocess module. Its main goal is to provide a much simpler, more intuitive, and "Pythonic" way to execute external commands.
The standard subprocess module is powerful but can be verbose and complex for common tasks. easyprocess simplifies the most common use cases into a single, easy-to-use class.
The Main Problem easyprocess Solves
Imagine you want to run a simple command like ls -l in Linux/macOS or dir in Windows and get its output.
Using the standard subprocess module:

import subprocess
try:
# This is quite verbose!
process = subprocess.Popen(
['ls', '-l'], # The command and its arguments as a list
stdout=subprocess.PIPE, # Capture standard output
stderr=subprocess.PIPE, # Capture standard error
text=True # Decode output as text
)
stdout, stderr = process.communicate()
if process.returncode == 0:
print("Command succeeded!")
print("Output:\n", stdout)
else:
print("Command failed!")
print("Error:\n", stderr)
except FileNotFoundError:
print("Error: 'ls' command not found.")
Using easyprocess:
from easyprocess import EasyProcess
# This is much cleaner and more readable!
p = EasyProcess(['ls', '-l']).call()
if p.return_code == 0:
print("Command succeeded!")
print("Output:\n", p.stdout)
else:
print("Command failed!")
print("Error:\n", p.stderr)
As you can see, easyprocess dramatically reduces the boilerplate code for a very common task.
Installation
First, you need to install it using pip:
pip install easyprocess
Core Usage and Examples
The heart of easyprocess is the EasyProcess class. The most common method is .call().

Running a Simple Command
Let's run the echo command.
from easyprocess import EasyProcess
# The command is passed as a list of strings
p = EasyProcess(['echo', 'Hello from EasyProcess!']).call()
# Check the return code (0 means success)
if p.return_code == 0:
# The output is available as a string in .stdout
print("Command Output:", p.stdout)
else:
# The error output is in .stderr
print("Command Error:", p.stderr)
print("Return Code:", p.return_code)
# Expected Output:
# Command Output: Hello from EasyProcess!
Handling Errors
What happens if you run a command that doesn't exist?
from easyprocess import EasyProcess
p = EasyProcess(['this_command_does_not_exist']).call()
# The return code will be non-zero (usually 127 or similar)
print(f"Return Code: {p.return_code}")
print(f"Stdout: '{p.stdout}'") # Will be an empty string
print(f"Stderr: '{p.stderr}'") # Will contain the error message
# Expected Output (on Linux/macOS):
# Return Code: 127
# Stdout: ''
# Stderr: '/bin/sh: this_command_does_not_exist: command not found'
Running Commands with Arguments
This is where easyprocess really shines. It handles arguments cleanly.
from easyprocess import EasyProcess
# Get the current working directory
p = EasyProcess(['pwd']).call()
print("Current Directory:", p.stdout.strip())
# List files in a specific directory
p = EasyProcess(['ls', '-l', '/tmp']).call()
print("\nContents of /tmp:\n", p.stdout)
Working with Different Environments
You can specify a custom working directory or environment variables.
import os
from easyprocess import EasyProcess
# Run a command in a specific directory
# Create a temp directory first for this example
os.makedirs('/tmp/my_test_dir', exist_ok=True)
p = EasyProcess(['pwd'], cwd='/tmp/my_test_dir').call()
print("Ran 'pwd' in /tmp/my_test_dir. Output:", p.stdout.strip())
# Run a command with a custom environment variable
p = EasyProcess(['echo', '$MY_VAR'], env={'MY_VAR': 'Hello World'}).call()
print("\nRan 'echo $MY_VAR' with a custom env. Output:", p.stdout.strip())
Checking if a Command Exists
A very useful feature is the .check() method, which simply returns True or False based on whether the command can be found and executed successfully.
from easyprocess import EasyProcess
# Check if 'python3' exists
if EasyProcess(['python3', '--version']).check():
print("python3 is available!")
else:
print("python3 is not available.")
# Check if a non-existent command exists
if EasyProcess(['non_existent_command']).check():
print("This will not be printed.")
else:
print("non_existent_command is not available, as expected.")
EasyProcess vs. subprocess: A Quick Comparison
| Feature | easyprocess |
subprocess |
|---|---|---|
| Simplicity | Very High. Designed for one-liners. | Lower. Requires more setup. |
| Main Method | .call() |
subprocess.run(), Popen(), etc. |
| Output Handling | p.stdout, p.stderr are simple strings. |
CompletedProcess.stdout is a bytes/string object. Requires text=True or .decode(). |
| Error Handling | Simple if p.return_code == 0: check. |
try...except blocks are common for FileNotFoundError. |
| Flexibility | Good for 95% of use cases. | Extremely flexible, can handle pipes, sockets, complex I/O redirection. |
| Dependencies | None. It's a pure Python library with no external dependencies. | Part of the standard library. No installation needed. |
When to Use easyprocess
- Quick scripts and automation: When you just need to run a command and get its output.
- Simple tests: Checking if a command-line tool is available and working.
- Beginners: It's much easier to learn than
subprocess. - Readability: When you want your code to be as clean and readable as possible.
When to Stick with subprocess
- Complex Pipelines: When you need to chain commands (e.g.,
cat file.txt | grep "error"). - Interactive Programs: When you need to send input to a command and read its output line-by-line (e.g.,
ssh,ftp). - Performance-Critical Code:
subprocess.Popencan offer more fine-grained control over process execution. - Low-Level Control: When you need to handle file descriptors directly.
Summary
easyprocess is a fantastic tool that lives up to its name. It makes running external processes in Python easy. If you find yourself writing repetitive subprocess boilerplate, give easyprocess a try. It will likely simplify your code and make your life a little bit easier.
