Python的subprocess.call和subprocess.run有什么区别

问题描述 投票:0回答:6

我已经尝试了解

subprocess.call
subprocess.run
之间的区别有一段时间了。我知道最后一个是 Python 3.5 的新功能,并且两者都基于
subprocess.Popen
,但我还无法理解其中的区别。

python subprocess
6个回答
82
投票

subprocess.call()
的定义明确提到:

相当于:

run(...).returncode
(除了不支持 inputcheck 参数)

正如Python 3.5的子流程文档所说:

在 Python 3.5 之前,这三个函数(即

.call()
.check_call()
.check_output()
)构成了子进程的高级 API。您现在可以在许多情况下使用
run()
,但许多现有代码都会调用这些函数。


常见的做法是,当某些功能被替换时,它们不会立即弃用,但某些版本有一个支持窗口。这有助于防止语言版本升级时旧代码的损坏。不知道以后

.call()
会不会被取代。但根据文档,我知道它们几乎相同。


33
投票

为了让任何想知道使用哪个的人都清楚:

subprocess.run() 是它可以处理的所有用例的推荐方法。 suprocess 文档 指出:

调用子流程的推荐方法是对它可以处理的所有用例使用 run() 函数。对于更高级的用例,可以直接使用底层的Popen接口。

subprocess.call()较旧的高级 API(Python 3.5 之前)的一部分。


5
投票

我不确定我是否同意其他答案。

我刚刚使用启动守护进程(Elasticsearch)的 bash 脚本度过了一段非常令人沮丧的时光。该命令仅提供可执行 Bash 脚本的路径。

但是

subprocess.run(...)
不会从此返回,而
subprocess.call(...)
会返回。

根据我的经验,如果您随后使用

subprocess.run(...)
停止该进程(例如,如果从终端运行,则为终端),这将杀死其中启动的守护进程。但
subprocess.call(...)
的情况并非如此:守护进程愉快地继续运行。

在这两种情况下我都设置了 kwarg

shell=True

我也尝试过

subprocess.run
ẁith
shell=False
(即如果省略
shell
则默认):没有变化。

我在

subprocess.run
中看不到任何其他可能的选项可以克服这个问题,所以据我所知,
subprocess.call
是根本不同的,尽管文档似乎这么说。在撰写本文时,文档说“您现在可以在许多情况下使用 run(),但许多现有代码都会调用这些函数。” (即旧功能,包括
call
)。

特别奇怪且令人沮丧的是(显然)当您运行启动守护程序的脚本时,例如:

./bin/elasticsearch -d -p pid

...它刚刚返回,您可以非常愉快地关闭终端。所以

subprocess.run
看起来有些奇怪,一些超级专家可能愿意解释一下。


1
投票

subprocess.call() 用于当您需要执行命令并让它等待命令完全完成时。当需要更多控制时,应使用 subprocess.run(),例如处理命令 stderr 和 stdout、捕获输出并能够定义命令执行超时。

如果我们不关心命令的输出,那么这样的例子是:

subprocess.call([r'C:\Program Files\Mozilla Firefox\Firefox.exe', '-new-tab', 'http://www.google.com/'])

0
投票

subprocess.call 只捕获您调用的子进程的返回代码

subprocess.run 除了返回代码之外,还允许您使用管道捕获 stdout 和 stdrr 输出

    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(),

需要强调的是,Run 和 Call 都是阻塞的,如果您需要保持它们并行执行或需要更高级的功能,您应该使用 subprocess.Popen,它并行运行并具有更高级的功能


-3
投票

我也不太清楚其中的差异。

我可以说,当您希望程序等待该进程完成然后再进入下一个进程时,您可以使用

subprocess.call()
。在
subprocess.run()
的情况下,程序将尝试一次运行所有进程,不可避免地导致程序崩溃。

© www.soinside.com 2019 - 2024. All rights reserved.