What's the difference between Python's subprocess.call and subprocess.run
Asked Answered
N

6

139

I've been trying to understand for a while now what's the difference between subprocess.call and subprocess.run. I know the last one is new on Python 3.5 and both are based on subprocess.Popen, but I'm not able to understand the difference yet.

Northernmost answered 19/11, 2016 at 20:30 Comment(1)
just check the documentation: call: This is equivalent to: run(...).returncode (except that the input and check parameters are not supported)Boito
L
84

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.

Lumumba answered 19/11, 2016 at 20:34 Comment(0)
I
35

To make it clear for anyone wanting to know which to use:

subprocess.run() is the recommended approach for all use cases it can handle. The suprocess documentation states:

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.call() is part of the Older high-level API (Prior to Python 3.5).

Idol answered 12/3, 2020 at 21:56 Comment(0)
J
5

I'm not sure I agree with the other answers.

I just had a very frustrating time with a bash script which starts a daemon process (Elasticsearch). The command merely supplies the path to the executable Bash script.

But subprocess.run(...) does not return from this, whereas subprocess.call(...) does.

From my experience, if you then stop the process (e.g. the Terminal if running from a Terminal) using subprocess.run(...) this kills off the daemon process started in it. But this is not the case with subprocess.call(...): the daemon carries on happily.

In both cases I set the kwarg shell=True.

I also tried subprocess.run ẁith shell=False (i.e. default if you omit shell): no change.

I can't see any other possible options in subprocess.run which might overcome this, so it appears, as far as I can tell that subprocess.call is fundamentally different, despite what the docs appear to say. At the time of writing the docs say "You can now use run() in many cases, but lots of existing code calls these functions." (i.e. the older functions, including call).

What is particularly strange, and frustrating, is that (obviously) when you run a script which starts a daemon, such as:

./bin/elasticsearch -d -p pid

... it just returns and you can close the Terminal quite happily. So there appears something quite odd about subprocess.run, which some super-expert might care to explain.

Jennelljenner answered 3/3, 2022 at 19:46 Comment(2)
I can't explain the differences better than the earlier answers; but this one is incorrect. subprocess.run is simply a newer and more versatile wrapper for the underlying subprocess.Popen interface, and subprocess.call(foo) is basically identical to subprocess.run(foo).returcode. Without seeing your actual code, it's hard to say what exactly you did or what went wrong.Noto
(Well, maybe I can; perhaps review #4256607)Noto
B
2

subprocess.call captures only return code of subprocess that you called.

subprocess.run allows you to capture, in addition to the return code, the stdout and stdrr outputs, with Pipes, for example

subprocess.run(
    [
        os.path.normpath(
            os.path.join(os.path.dirname(os.environ.get("comspec")), "wbem", "wmic.exe")
        ),
        "csproduct",
        "get",
        "UUID",
    ],
    stdout=subprocess.PIPE,
    shell=True,
).stdout.splitlines(),

It is important to highlight that both Run and Call are blocking, if you need to keep their execution in parallel or need more advanced functions, you should use subprocess.Popen, that running in parallel and have much more advanced features.

Bentham answered 29/10, 2023 at 16:35 Comment(0)
X
1

subprocess.call() is to be used when you need to execute a command and have it wait until the command has fully completed. subprocess.run() should be used when more control is needed such as handling the commands stderr and stdout, capturing output and being able to define the command execution timeout.

If we didnt care about the output of the command, then an example of this would be:

subprocess.call([r'C:\Program Files\Mozilla Firefox\Firefox.exe', '-new-tab', 'http://www.google.com/'])
Xantho answered 15/7, 2023 at 9:35 Comment(0)
A
-3

I am not fully clear on the differences either.

I can say that you use subprocess.call() when you want the program to wait for the process to complete before moving onto the next process. In the case of subprocess.run(), the program will attempt to run all the processes at once, inevitably causing the program to crash.

Accelerometer answered 7/7, 2022 at 9:38 Comment(3)
This is completely wrong. The earlier answers here explain the differences. subprocess.run is simply a newer and more versatile interface to the underlying subprocess.Popen interface.Noto
@tripleee, but isn't this answer pretty much saying what https://mcmap.net/q/166071/-what-39-s-the-difference-between-python-39-s-subprocess-call-and-subprocess-run does?Obstetric
@beedell.rokejulianlockhart Indeed, I have downvoted that too. But sure, I'll copy the comment over.Noto

© 2022 - 2024 — McMap. All rights reserved.