Explain Codes LogoExplain Codes Logo

How do I execute a program or call a system command?

python
subprocess
process-control
io-streaming
Anton ShumikhinbyAnton Shumikhin·Nov 4, 2024
TLDR

For Python versions 3.5 and above, leverage subprocess.run() of the subprocess module to execute system commands.

Take echo for instance:

import subprocess # "Time to shine!" subprocess.run(['echo', 'Hello World'])

The output can be captured using capture_output=True:

result = subprocess.run(['echo', 'Hello World'], capture_output=True) print(result.stdout) # Pow! Hello World

In Python <3.5, use subprocess.call() as a substitute for run:

import subprocess subprocess.call(['echo', 'Hello World'])

Mastering Process Control: subprocess.Popen

For complex subprocess interactions, real-time control of the process I/O, the mighty subprocess.Popen comes to rescue! Ideal when your process requires timely outputs or inputs.

An example of subprocess.Popen usage:

import subprocess # Start the magic! p = subprocess.Popen(['python', 'echo_script.py'], stdout=subprocess.PIPE) # Voila! Line by line output for line in iter(p.stdout.readline, b''): print(line.decode('utf-8')) # Prints Oh la la! every line

Ensure to "clean your room" — terminate your subprocesses properly to avoid ghost processes.👻

Safety First: Sanitize inputs

While playing with subprocesses, you should be like a goalkeeper— keeping the injections attacks at bay. Always remember to sanitize user inputs, especially if your command uses any user-generated data.

Check out sanitized inputs in action:

import subprocess from shlex import quote user_input = input("Enter a file name:") safe_input = quote(user_input) # "Bubble-wrap" the user input subprocess.run(['cat', safe_input]) # Feed it the sanitized input

Redirect, Detach, Repeat: Advanced subprocess control

Subprocesses may need to detach or redirect errors for specific functionalities. subprocess.Popen offers multiple options, such as stderr and creation flags like DETACHED_PROCESS and CREATE_NEW_CONSOLE on Windows.

Redirecting errors — keep calm and redirect:

import subprocess # Guide errors to stdout subprocess.Popen(['bad_command'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

Creating a detached process on Windows — a little "me time":

import subprocess # Detach and go on a holiday! subprocess.Popen(['start', 'my_script.bat'], creationflags=subprocess.DETACHED_PROCESS)

Remember, just as every superhero has a unique power, every operating system has its own behavior. So, if you're targeting multiple platforms, make sure your script runs consistently across all of them.

Emulating subprocesses and cross-platform consistency

Subprocesses can be naughty and behave differently across OS environments. Know their nuances for termination and streaming I/O on varying platforms. For more control, you can use subprocess.Popen to emulate the os.system() behavior in complex cases without setting stdout and stderr.

File handling, FreeBSD style:

import subprocess # Say "Hello FreeBSD" to the World! subprocess.Popen(['echo', 'Hello FreeBSD'], close_fds=True)

To ensure your script remains consistent across different OSes, brace it with thorough testing and conditional logic:

import platform import subprocess if platform.system() == 'Windows': # This is for the MS lovers elif platform.system() == 'Linux': # Penguin-based OS enthusiasts, you're covered

For faster and more secure alternative execution methods, consider the os.exec* and os.spawn* families, where the called command isn't wrapped in a shell.