The Raspberry Pi is a popular single-board computer that runs Linux, with Python as its official programming language. As a Raspberry Pi user, you‘ll likely need to execute Linux commands regularly for tasks like file management, user administration, installing packages etc.
While you can always run these commands directly in the terminal, it can get tedious entering the terminal over and over, especially if executing commands from within Python scripts. Fortunately, Python provides simple ways to run system commands from within your code itself.
In this comprehensive guide, we‘ll explore the two main methods to execute shell commands programmatically in Python on Raspberry Pi:
- Using the os module
- Using the subprocess module
We‘ll see examples of running common Linux commands like ls, mkdir, adduser etc. using both these approaches.
Overview of OS and Subprocess Modules
The os module is a built-in Python module that provides convenient access to operating system functionality. It contains functions like os.system(), os.popen() etc. for executing system commands.
The subprocess module allows spawning new processes to run commands. It gives more flexibility than os module and handles complex scenarios like piping output between multiple commands.
So the os module is simpler, while subprocess module is more full-featured. We‘ll cover usage of both in this guide.
1. Executing Commands with os module
To use the os module in Python, first import it:
import os
The os module provides two chief ways to run shell commands:
os.system()os.popen()
Let‘s explore them one by one with examples.
1.1 os.system()
The os.system() method executes the command passed to it in a subshell.
Here is the syntax:
os.system(‘command‘)
Let‘s see some examples of running common Linux commands with os.system().
Print current working directory:
import os
os.system(‘pwd‘)
This will print the output directly to the terminal.
List files in directory:
import os
os.system(‘ls‘)
Create a directory:
import os
os.system(‘mkdir testdirectory‘)
Add a new user:
import os
os.system(‘sudo adduser newuser‘)
And so on.
One limitation of os.system() is that it doesn‘t allow capturing the output programmatically for further processing. For that, os.popen() is useful.
1.2 os.popen()
The os.popen() method opens a pipe to the command passed to it and returns a file handle. We can use this handle to read the output of the command.
Here is how to use it:
import os
stream = os.popen(‘command‘)
output = stream.read()
The command‘s output is stored in the output variable as a string.
Let‘s see some examples.
Store ls output:
import os
stream = os.popen(‘ls‘)
output = stream.read()
print(output)
We can process the stored output further according to our needs.
Count files in directory:
import os
stream = os.popen(‘ls | wc -l‘)
output = stream.read()
count = int(output)
print(f"Total files: {count}")
Here we piped the ls output to wc -l to count lines, stored it in a variable, converted to integer, and printed the count.
So with os.popen(), you can read command outputs in your Python code for further processing that would be difficult with os.system().
2. Executing Commands with subprocess
The subprocess module provides more flexibility in running shell commands from Python code. It allows spawning child processes asynchronously and offers better ways to feed input or pipe output between processes.
To start using subprocess, import it:
import subprocess
The primary method that subprocess provides for running commands is subprocess.run().
2.1 subprocess.run()
The subprocess.run() method runs the command passed to it in a subprocess and returns a CompletedProcess object.
Here is its standard syntax:
result = subprocess.run([‘command‘, ‘arg1‘, ‘arg2‘])
We pass the command and its arguments as a list to run().
Let‘s see some examples:
List files:
import subprocess
result = subprocess.run([‘ls‘, ‘-l‘])
Print disk usage:
import subprocess
result = subprocess.run([‘df‘, ‘-h‘])
The result object contains useful information like the command‘s exit code, output etc. which we can access:
print(f"Exit code: {result.returncode}")
print(f"Output: {result.stdout}")
print(f"Errors: {result.stderr}")
By default, the output streams are buffered. To print the output directly to terminal, use:
result = subprocess.run([‘ls‘], stdout=subprocess.PIPE, text=True)
print(result.stdout)
The text argument decodes the bytes output to a string.
We can also provide shell-style string commands instead of list format:
subprocess.run(‘ls -l | grep .py‘, shell=True)
The shell=True argument runs the command string through the shell.
2.2 Interactive Input/Output
A great benefit of the subprocess module is the ability pipe input or output interactively between processes.
Let‘s see an example of providing input to a command via stdin.
Pipe input to bash:
import subprocess
proc = subprocess.Popen([‘bash‘], stdin=subprocess.PIPE)
proc.stdin.write(b‘echo Hello World\n‘)
proc.stdin.write(b‘exit\n‘)
output = proc.communicate()[0]
print(output.decode().strip())
Here we get a process handle via Popen(), write some input commands to it, then print the output after the process exits.
Similarly, we can pipe output of one process as input to another using subprocess pipes.
Count files:
import subprocess
proc1 = subprocess.Popen([‘ls‘], stdout=subprocess.PIPE)
proc2 = subprocess.Popen([‘wc‘, ‘-l‘], stdin=proc1.stdout,
stdout=subprocess.PIPE)
output = proc2.communicate()[0]
print(f"Total files: {output.decode().strip()}")
So subprocess makes it easy to handle input/output programmatically with Python.
Best Practices for Running Commands
When executing system commands from Python, keep in mind:
- Always sanitize user input before substituting into commands
- Prefer subprocess over os module for better control and output handling
- Consider edge cases carefully – exit codes, errors, output buffering etc
- Don‘t assume commands succeeded, check return codes
- Validate permissions before file/dir operations
Adopting these best practices will make your script‘s command execution more secure, robust and deterministic.
Conclusion
Executing Linux commands from within Python scripts is extremely useful for automating admin tasks, implementing CLI tools, and simplifying workflows.
We learned two approaches for running system commands using Python on Raspberry Pi:
- The os module – provides
os.system()andos.popen() - The subprocess module – gives more flexibility via
subprocess.run()etc.
The os module offers a simple interface for basic command execution. Subprocess gives finer-grained control over spawning processes and managing input/output streams.
So in summary:
- Use
os.system()for fire-and-forget command running - Use
os.popen()to programmatically access command output - Use
subprocesswhen you need better output handling or process control
By mastering these methods, you can easily automate almost any Linux administration or command line task with Python scripts on your Raspberry Pi.


