编写Python shell脚本时使用subprocess.call()或os.system()是不是很糟糕?

时间:2017-06-09 13:58:09

标签: python linux scripting

我正在研究Python是否可以替换Bash用于shell脚本编写目的。我已经看到Python可以使用subprocess.call()或os.system()执行Linux命令。但是我在某处读过(忘了文章的链接)使用这些是件坏事。这是真的吗?

如果是,那么为什么这是一件坏事呢?

如果没有,那么可以说Python确实可以替代Bash进行脚本编写,因为我可以使用2个函数调用之一执行Linux命令吗?

注意:如果我没有弄错的话,不推荐使用os.system(),而应该使用subprocess.call(),但这不是问题的主要内容。

2 个答案:

答案 0 :(得分:2)

使用os.system()subprocess.call(..., shell=True)无法替换 shell,因为他们实际上使用 shell。

os.system("foo")实际上调用了sh -c "foo" - 也就是说,它运行foo作为shell脚本。然后,使用它,替换 shell。对于subprocess.call("foo", shell=True),情况也是如此。

使用subprocess.Popen和该系列中的函数可以替换shell,但这通常会导致冗长且难以处理的代码。

考虑以下shell脚本:

#!/bin/sh
foo "$1" | bar "$2"

现在,让我们看一下在Python中以不会启动任何shell的方式重现它所需的内容:

#!/usr/bin/env python
import subprocess, sys

p1 = subprocess.Popen(["foo", sys.argv[1]], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["bar", sys.argv[2]], stdin=p1.stdout)
sys.exit(p2.wait())

我们从19个字符(在shebang之后)到148个字符(在shebang和import之后) - 这是一个完全琐碎的脚本,一个没有使用诸如进程替换之类的更高级功能,命令替换等。

答案 1 :(得分:0)

通常,从您自己的流程创建另一个流程并不是一件坏事。 人们经常在狂欢中这样做。

然而,人们总是应该问自己,完成你需要做的任务的最佳环境是什么。 例如,我可以轻松地从文件中调用python脚本到cut(linux工具)。但是,首先打开python解释器,然后保存cut的输出,然后再次保存它的开销可能高于检查如何将bash-tool与man一起使用。

但是,收集来自另一个“严重”程序的输出以对该输出进行进一步计算,是的,你可以很好地处理子进程(尽管我会选择将该输出存储在文件中然后只读入文件中我需要重新运行我的脚本。)

这就是启动子流程可能会变得棘手的地方:根据您打开新子流程的方式,您不能再依赖环境变量了。 特别是在处理大量输入数据时,子进程的输出不会被进一步传输,因此会被收集到内存中直到程序完成,这可能会导致内存问题。

简而言之:如果使用python比组合仅使用bash的工具更快地解决问题,请确保执行此操作。如果这涉及启动严重的子流程,那么。但是,如果你想用python替换bash,不要这样做。