os.system("pwd") 和 os.getcwd() 之间的区别

Difference between os.system("pwd") and os.getcwd()

我对以下 3 个函数族有一个基本的疑问:

例如,我想知道 Python 中的当前工作目录。因此,实现这一目标的一些方法可能是:

os.system("pwd")

os.getcwd()

subprocess.Popen(['pwd'], stdout=PIPE, stderr=PIPE)

我在网上找到了很多资源来区分上面的第三个和其他的,但是找不到太多关于上面第一个 2 之间的区别的信息。

请帮我理解这三者的区别,尤其是

  1. 从输出的角度
  2. 从性能的角度来看
  3. 从实现的角度来看,即这三个在内部是如何实现的,例如,对于它们中的每一个,它们是否产生一个新进程,它们如何与内核交互等。

任何指向我自己参考的指针也将不胜感激。

os.getcwd() 调用会更快,因为它不依赖任何外部依赖项。您的第一个和最后一个示例都执行一个单独的进程,pwd 系统命令,return 其输出为字符串。好吧,您的 Popen() 示例将要求您使用另一个调用来获取其输出,但我离题了。

根本不需要调用外部命令;只需使用 os.getcwd().

这三者之间的主要区别在于只有一个 os.getcwd() 保证有效。

另外两个依赖于 pwd,并非在所有操作系统中都可用。

正如@Will 在 中提到的,没有必要为此信息生成一个单独的进程;它可能会给你意想不到的结果。

发现性能问题的最好方法是自己测量。 Python 实施各不相同。同样,如果您想了解它们是如何实现的,请阅读源代码。

所有这些机制可能会在类 UNIX 系统上调用相同的底层 C 库接口 getcwd(3)。只是有些人使用外部程序到达那里。

os.system("pwd") 运行s a shell(第一个过程)到 运行 外部程序 pwd(第二个过程)。因此性能会很差并且不可移植,因为 pwd 并非在所有支持 Python 的平台上实现。输出变为 stdout,它未被捕获以供程序使用。

你省略了函数popen:

wd = os.popen('pwd').readline()

这被认为已过时,os.system() 也被认为已过时,两者都被 subprocess 取代。 popen 实现可能使用 C 运行 时间库函数 popen,它还会调用 shell 来执行命令,因此性能可能很差。

subprocess 模块旨在替换这些旧接口,因此出现了重复。一个优点是 shell 的使用是可选的,在这种情况下您不需要它。但是你的代码不完整:

proc = subprocess.Popen(['pwd'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
wd, err = proc.communicate()
if err:
    print >> sys.stderr, err
else:
    print wd,

因为没有 shell 进程,所以效率会更高。但实际上你应该自己在自己的系统上对其进行基准测试。

目前的所有接口都是一般 - 它们用于运行大量命令和外部程序。它们经常被滥用和使用不当的事实反映了程序员缺乏理解(或懒惰)。

我们还剩下os.getcwd()。它可能是作为对 C 库接口的直接调用来实现的,但可能会绕过它来调用内核。检查您的实现的源代码。没有子进程,所以更快。

您关于重复的观点也适用于许多其他接口,os.remove()os.mkdir()os.stat(),等等。关键是它们快速且便携,它们不 运行 其他程序。

与使用 shell 相比,拥有这些直接接口是使用像 Python 这样的语言的主要优势。 Bash 没有用于获取当前目录、获取文件大小、删除文件等的内置命令。它依赖于外部程序 - python 没有。

偶尔会有一个恼人的差异。 os.getcwd() 函数似乎在内部使用 os.realpath,因此如果您所在的目录是符号链接,您将获得与 pwd 不同的结果。如果还意味着您可能会得到一个与您执行 os.chdir 的目录不同的目录。

% pwd
/tmp
% pwd -P
/ram/tmp

% python3 -c "import os ; os.chdir('/tmp') ; print(os.getcwd())"
/ram/tmp
% python2 -c "import os ; os.chdir('/tmp') ; print os.getcwd()"
/ram/tmp