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
45 Python: subprocess and running a bash script with multiple arguments ยท 51 Can subprocess.call be invoked without waiting for process to finish? More on stackoverflow.com
๐ŸŒ stackoverflow.com
January 6, 2020
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
[deleted by user]
No, you need to make use of the subprocess.Popen() function to create a sequence. More on reddit.com
๐ŸŒ r/learnpython
7
0
September 17, 2021
๐ŸŒ
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
๐ŸŒ
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.
Find elsewhere
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() ...
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
    
๐ŸŒ
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
๐ŸŒ
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:
๐ŸŒ
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.
๐ŸŒ
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 ...
๐ŸŒ
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().
๐ŸŒ
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.
๐ŸŒ
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.
๐ŸŒ
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...
๐ŸŒ
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).
๐ŸŒ
Medium
medium.com โ€บ @rinu.gour123 โ€บ python-subprocess-module-subprocess-vs-multiprocessing-baa4c83c6a63
Python Subprocess Module | Subprocess vs Multiprocessing | by Rinu Gour | Medium
October 12, 2018 - 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.