在Python中,open(file).read()和subprocess([' cat',file])之间的区别是什么?是否优先选择其中一个?

时间:2016-01-26 17:57:43

标签: python

我想说我想从/proc/meminfo读取RAM使用情况。我能想到有两种基本的方法可以做到这一点。

使用shell命令

output = subprocess.check_output('cat /proc/meminfo', shell=True)
# or output = subprocess.check_output(['cat', '/proc/meminfo'])
lines = output.splitlines()

使用open()

with open('/proc/meminfo') as meminfo:
    output = meminfo.read()
lines = output.splitlines()

我的问题是这两种方法有什么区别?是否有显着的性能差异?我的假设是使用open()是首选方法,因为使用shell命令有点hackish并且可能与系统有关,但我无法找到任何关于此的信息所以我认为我是问。

1 个答案:

答案 0 :(得分:4)

...所以,让我们看看output = subprocess.check_output('cat /proc/meminfo', shell=True)做了什么:

  • 使用mkfifo()创建一个FIFO对,并生成一个运行sh -c 'cat /proc/meminfo'的shell写入FIFO的输入端(而Python解释器本身则在另一端监视输出,使用{ {1}}调用或阻止IO操作)。这意味着打开select(),打开它所依赖的所有库等等。
  • shell将这些参数解析为代码。如果不是打开/bin/sh,这可能会很危险。您改为开放/proc/meminfo
  • shell分叉子进程(可选; shell可能有一个隐式/tmp/$(rm -rf ~)/pwned.txt),然后使用exec系统调用以execve的argv调用/bin/cat - 意味着['cat', '/proc/meminfo']再次作为可执行文件加载,其动态库具有所需的所有性能开销。
  • /bin/cat然后打开/bin/cat,从中读取并写入其stdout
  • 如果shell没有使用隐式 - /proc/meminfo优化,则等待exec可执行文件完成并使用/bin/cat - 系列调用进行退出。
  • Python解释器从FIFO的远端读取,直到它提供EOF(直到wait()关闭其输出管道后才会发生,可能是退出),然后使用{{1} -family调用以检索有关它如何退出的shell的信息,检查退出状态以确定是否发生错误。

现在,让我们看看cat做了什么:

  • 使用wait()系统调用
  • 打开文件
  • 使用open('/proc/meminfo').read()系统调用
  • 读取文件
  • 删除文件上的引用计数,允许使用open()系统调用关闭它(立即或在未来的垃圾收集过程中)。

这些事情中的一个很多,很多很多比另一个更有效率和更明智。