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 之间的区别的信息。
请帮我理解这三者的区别,尤其是
- 从输出的角度
- 从性能的角度来看
- 从实现的角度来看,即这三个在内部是如何实现的,例如,对于它们中的每一个,它们是否产生一个新进程,它们如何与内核交互等。
任何指向我自己参考的指针也将不胜感激。
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
我对以下 3 个函数族有一个基本的疑问:
例如,我想知道 Python 中的当前工作目录。因此,实现这一目标的一些方法可能是:
os.system("pwd")
os.getcwd()
subprocess.Popen(['pwd'], stdout=PIPE, stderr=PIPE)
我在网上找到了很多资源来区分上面的第三个和其他的,但是找不到太多关于上面第一个 2 之间的区别的信息。
请帮我理解这三者的区别,尤其是
- 从输出的角度
- 从性能的角度来看
- 从实现的角度来看,即这三个在内部是如何实现的,例如,对于它们中的每一个,它们是否产生一个新进程,它们如何与内核交互等。
任何指向我自己参考的指针也将不胜感激。
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