The definition of subprocess.call() clearly mentions:

It is equivalent to: run(...).returncode (except that the input and check parameters are not supported)

As the Python 3.5's subprocess document says:

Prior to Python 3.5, these three functions (i.e. .call(), .check_call(), .check_output()) comprised the high level API to subprocess. You can now use run() in many cases, but lots of existing code calls these functions.


It is a common practice that when some functions are replaced, they are not instantly deprecated but there is a support window for them for some versions. This helps in preventing the breakage of older code when the language version is upgraded. I do not know whether .call() is going to be replaced in the future or not. But based on the document, what I know is that they are pretty much same.

Answer from Moinuddin Quadri on Stack Overflow
🌐
Python
docs.python.org › 3 › library › subprocess.html
subprocess — Subprocess management
2 weeks ago - To determine if the shell failed to find the requested application, it is necessary to check the return code or output from the subprocess. A ValueError will be raised if Popen is called with invalid arguments. check_call() and check_output() will raise CalledProcessError if the called process returns a non-zero return code. All of the functions and methods that accept a timeout parameter, such as run() and Popen.communicate() will raise TimeoutExpired if the timeout expires before the process exits.
Discussions

os.popen vs subprocess.run for simple commands

About 13 years ago, the older, deprecated per-os popen2/popen3/popen4 calls were removed, and os.popen() was implemented in terms of subprocess.Popen (just like subprocess.run is).:

https://github.com/python/cpython/commit/c2f93dc2e42b48a20578599407b0bb51a6663d09#diff-405b29928f2a3ae216e45afe9b5d0c60

So, I don't think the current os.popen() is deprecated anymore (I can't see any indication that it is; that was for the older versions which were removed).

Therefore, I think you can safely use it if you want. But, keep in mind that the popen() concept was pretty Unix specific, and isn't obvious to everyone that it's running a subprocess, whereas that should be fairly obvious from subprocess.run().

You could consider making a dictionary of keyword args (that you re-use), and passing that to subprocess.run(), if it's just the length of the calling lines that is concerning you:

runargs = {'shell': True, 'capture_output': True, 'text': True }
output = subprocess.run('<command>', **runargs).stdout
More on reddit.com
🌐 r/learnpython
5
4
June 20, 2020
python - What is the difference between subprocess.popen and subprocess.run - Stack Overflow
4 Is there a way to wait for another python script called from current script (using subprocess.Propen()) till its complete? 0 Why am i getting a host not found error when running my python ping script? More on stackoverflow.com
🌐 stackoverflow.com
python - What's the difference between subprocess Popen and call (how can I use them)? - Stack Overflow
Both apply to either subprocess.Popen or subprocess.call. Set the keyword argument shell = True or executable = /path/to/the/shell and specify the command just as you have it there. Since you're just redirecting the output to a file, set the keyword argument ... Popen doesn't block, allowing you to interact with the process while it's running, or continue with other things in your Python ... More on stackoverflow.com
🌐 stackoverflow.com
How subprocess run() works?
Running python sys.executable in pycharm shows it uses virtual environment interpreter (venv) PS C:\Users\SJ\Desktop\Programs\Python\PyTest> python Python 3.11.4 (tags/v3.11.4:d2340ef, Jun 7 2023, 05:45:37) [MSC v.1934 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" ... More on discuss.python.org
🌐 discuss.python.org
7
0
June 21, 2024
People also ask

What does subprocess run do?
Subprocess runs the command, waits for the procedure to complete, and then returns a "Completed process" artifact.
🌐
simplilearn.com
simplilearn.com › home › resources › software development › python subprocess: master external command execution
Python Subprocess: Master External Command Execution
Is subprocess a standard Python library?
With the help of the subprocess library, we can run and control subprocesses right from Python.
🌐
simplilearn.com
simplilearn.com › home › resources › software development › python subprocess: master external command execution
Python Subprocess: Master External Command Execution
🌐
DataCamp
datacamp.com › tutorial › python-subprocess
An Introduction to Python Subprocess: Basics and Examples | DataCamp
September 12, 2025 - The command's return code will be stored in the return_code variable, which will be zero if the command was successful, and non-zero if it failed. subprocess.call() is useful when you want to run a command and check the return code, but do not need to capture the output.
🌐
Copdips
copdips.com › 2022 › 12 › python-difference-on-subprocess-run-call-check_call-check_output.html
Python difference on subprocess run(), call(), check_call(), check_output() - A code to remember
December 1, 2022 - Prior to Python 3.5, these three functions (subprocess.call(), subprocess.check_call(), subprocess.check_output()) comprised the high level API to subprocess. You can now use subprocess.run() in many cases, but lots of existing code calls these functions. subprocess.run default behavior accepts arguments in list ·
🌐
Reddit
reddit.com › r/learnpython › os.popen vs subprocess.run for simple commands
r/learnpython on Reddit: os.popen vs subprocess.run for simple commands
June 20, 2020 -

For scripts where I've had to run shell commands and get their output, I have used subprocess.run() as I have read that it is the recommended way of running shell commands. However, I have just learned of os.popen() which seems much simpler to use if you don't need any of the extra functionality of subprocess, as shown below:

output = os.popen('<command>').read()

vs

output = subprocess.run('<command>', shell=True, capture_output=True, text=True).stdout

If I don't need any of subprocess's extra functionalities, is there any reason for me not to use os.popen() for this simple use case? Any hidden, under-the-hood reasons?

I ask this because popen is labelled as deprecated and everywhere recommends subprocess instead. Thanks in advance.

Top answer
1 of 3
1

About 13 years ago, the older, deprecated per-os popen2/popen3/popen4 calls were removed, and os.popen() was implemented in terms of subprocess.Popen (just like subprocess.run is).:

https://github.com/python/cpython/commit/c2f93dc2e42b48a20578599407b0bb51a6663d09#diff-405b29928f2a3ae216e45afe9b5d0c60

So, I don't think the current os.popen() is deprecated anymore (I can't see any indication that it is; that was for the older versions which were removed).

Therefore, I think you can safely use it if you want. But, keep in mind that the popen() concept was pretty Unix specific, and isn't obvious to everyone that it's running a subprocess, whereas that should be fairly obvious from subprocess.run().

You could consider making a dictionary of keyword args (that you re-use), and passing that to subprocess.run(), if it's just the length of the calling lines that is concerning you:

runargs = {'shell': True, 'capture_output': True, 'text': True }
output = subprocess.run('<command>', **runargs).stdout
2 of 3
1

I'll still use popen here and there....

Use it with yield for best results

>>> from os import popen                                                         
>>> 
>>> def cmd_out(cmd):
...     for out in popen(cmd):
...         yield out
... 
>>> 
>>> _ = [print(result) for result in cmd_out('service --status-all')]
 [ + ]  acpid

 [ - ]  alsa-utils

 [ - ]  anacron

 [ + ]  apparmor

 [ + ]  apport

 [ + ]  avahi-daemon

 [ + ]  bluetooth

 [ - ]  console-setup.sh

 [ + ]  cron

 [ - ]  cryptdisks

 [ - ]  cryptdisks-early

 [ + ]  cups

 [ + ]  cups-browsed

 [ + ]  dbus

 [ - ]  dns-clean

 [ + ]  gdm3

 [ + ]  grub-common

 [ - ]  hwclock.sh

 [ + ]  irqbalance

 [ + ]  kerneloops

 [ - ]  keyboard-setup.sh

 [ + ]  kmod

 [ + ]  mpd

 [ + ]  network-manager

 [ + ]  networking

 [ - ]  plymouth

 [ - ]  plymouth-log

 [ - ]  pppd-dns

 [ + ]  procps

 [ - ]  rsync

 [ + ]  rsyslog

 [ - ]  saned

 [ + ]  sddm

 [ + ]  speech-dispatcher

 [ - ]  spice-vdagent

 [ - ]  ssh

 [ - ]  supervisor

 [ - ]  tor

 [ + ]  udev

 [ + ]  ufw

 [ + ]  unattended-upgrades

 [ - ]  uuidd

 [ + ]  virtualbox

 [ + ]  whoopsie

 [ - ]  x11-common
Find elsewhere
🌐
programming review
programming-review.com › python › subprocess
PYTHON SUBPROCESS — PROGRAMMING REVIEW
subprocess.run() is more powerful than call(), it can return the return code, the output and the error.
Top answer
1 of 2
296

subprocess.run() was added in Python 3.5 as a simplification over subprocess.Popen when you just want to execute a command and wait until it finishes, but you don't want to do anything else in the mean time. For other cases, you still need to use subprocess.Popen.

The main difference is that subprocess.run() executes a command and waits for it to finish, while with subprocess.Popen you can continue doing your stuff while the process finishes and then just repeatedly call Popen.communicate() yourself to pass and receive data to your process. Secondly, subprocess.run() returns subprocess.CompletedProcess.

subprocess.run() just wraps Popen and Popen.communicate() so you don't need to make a loop to pass/receive data or wait for the process to finish.

Check the official documentation for info on which params subprocess.run() pass to Popen and communicate().

2 of 2
11

Both available in Python by default.

The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle. For more advanced use cases, the underlying Popen interface can be used directly.

-subprocess.run:

import subprocess
import sys

result = subprocess.run([sys.executable, "-c", "print('ocean')"])

-subprocess.popen: run multiple command line with subprocess, communicate method waits for the process to finish and finally prints the stdout and stderr as a tuple

EX:

import subprocess
process = subprocess.Popen(shell_cmd,
                     stdout = subprocess.PIPE, 
                     stderr = subprocess.PIPE,
                     text = True,
                     shell = True
                     )
std_out, std_err = process.communicate()
std_out.strip(), std_err
🌐
Linux find Examples
queirozf.com › entries › python-3-subprocess-examples
Python 3 Subprocess Examples
November 26, 2022 - As of Python version 3.5,run() should be used instead of call(). run() returns a CompletedProcess object instead of the process return code. A CompletedProcess object has attributes like args, returncode, etc. subprocess.CompletedProcess · other functions like check_call() and check_output() ...
🌐
Simplilearn
simplilearn.com › home › resources › software development › python subprocess: master external command execution
Python Subprocess: Master External Command Execution
December 15, 2025 - Learn about Python's subprocess module for executing external commands. Discover how to manage processes and handle inputs/outputs efficiently.
Address   5851 Legacy Circle, 6th Floor, Plano, TX 75024 United States
🌐
Codecademy
codecademy.com › article › python-subprocess-tutorial-master-run-and-popen-commands-with-examples
Python Subprocess Tutorial: Master run() and Popen() Commands (with Examples) | Codecademy
Learn how to use Python’s `subprocess` module, including `run()` and `Popen()` to execute shell commands, capture output, and control processes with real-world examples.
Top answer
1 of 2
325

There are two ways to do the redirect. Both apply to either subprocess.Popen or subprocess.call.

  1. Set the keyword argument shell = True or executable = /path/to/the/shell and specify the command just as you have it there.

  2. Since you're just redirecting the output to a file, set the keyword argument

    stdout = an_open_writeable_file_object
    

    where the object points to the output file.

subprocess.Popen is more general than subprocess.call.

Popen doesn't block, allowing you to interact with the process while it's running, or continue with other things in your Python program. The call to Popen returns a Popen object.

call does block. While it supports all the same arguments as the Popen constructor, so you can still set the process' output, environmental variables, etc., your script waits for the program to complete, and call returns a code representing the process' exit status.

returncode = call(*args, **kwargs) 

is basically the same as calling

returncode = Popen(*args, **kwargs).wait()

call is just a convenience function. It's implementation in CPython is in subprocess.py:

def call(*popenargs, timeout=None, **kwargs):
    """Run command with arguments.  Wait for command to complete or
    timeout, then return the returncode attribute.

    The arguments are the same as for the Popen constructor.  Example:

    retcode = call(["ls", "-l"])
    """
    with Popen(*popenargs, **kwargs) as p:
        try:
            return p.wait(timeout=timeout)
        except:
            p.kill()
            p.wait()
            raise

As you can see, it's a thin wrapper around Popen.

2 of 2
63

The other answer is very complete, but here is a rule of thumb:

  • call is blocking:

    call('notepad.exe')
    print('hello')  # only executed when notepad is closed
    
  • Popen is non-blocking:

    Popen('notepad.exe')
    print('hello')  # immediately executed
    
🌐
GeeksforGeeks
geeksforgeeks.org › python › retrieving-the-output-of-subprocesscall-in-python
Retrieving the output of subprocess.call() in Python - GeeksforGeeks
July 23, 2025 - The subprocess.call() function in Python is used to run a command described by its arguments. Suppose you need to retrieve the output of the command executed by subprocess.call().
🌐
Real Python
realpython.com › python-subprocess
The subprocess Module: Wrapping Programs With Python – Real Python
January 18, 2025 - The run() function makes a system call, foregoing the need for a shell. You’ll cover interaction with the shell in a later section. Shells typically do their own tokenization, which is why you just write the commands as one long string on ...
🌐
Python Morsels
pythonmorsels.com › running-subprocesses-in-python
Running subprocesses in Python - Python Morsels
March 6, 2025 - This is similar to the syntax that we would use if we were calling this process ourselves from our system's command-line. By default, the run function doesn't capture the output of the subprocess. So any output that the subprocess generates is shown in the terminal window, just as if we ran the process from outside of our Python process:
🌐
DataFlair
data-flair.training › blogs › python-subprocess-module
Python Subprocess Module | Subprocess vs Multiprocessing - DataFlair
March 8, 2021 - It finds its proposal in PEP 324 for version 2.4 and replaces the following modules/ functions in Python: ... The call() function from the subprocess module lets us run a command, wait for it to complete, and get its return code.
🌐
Quora
quora.com › Whats-the-difference-between-os-system-and-subprocess-call-in-Python
What's the difference between os.system and subprocess.call in Python? - Quora
Answer (1 of 3): The os.system(command) method executes the command in subshell. The subprocess.Popen(command_args, …..) method executes the command args as new process (child process). You can send / receive data to stdout /stdin using communicate() of Popen object. The main difference between...
🌐
Dataquest
dataquest.io › blog › python-subprocess
Python Subprocess: The Simple Beginner's Tutorial (2023)
February 19, 2025 - In fact, this is the same as passing /usr/local/bin/python -c print('This is a subprocess') to the command line. Most of the code in this article will be in this format because it's easier to show the features of the run function. However, you can always call another Python script containing the same code.
🌐
Code Calamity
codecalamity.com › home › run, subprocess, run!
Run, Subprocess, Run! - Code Calamity
February 4, 2021 - These made life a lot easier, as you could now have easy interaction with the process pipes, running it as a direct call or opening a new shell first, and more. The downside was the inconvenience of having to switch between them depending on needs, as they all had different outputs considering how you interacted with them. That all changed in Python 3.5, with the introduction of subprocess.run (for older versions check out reusables.run).