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

Posted

技术标签:

【中文标题】os.system("pwd") 和 os.getcwd() 的区别【英文标题】:Difference between os.system("pwd") and os.getcwd() 【发布时间】:2016-10-04 22:59:42 【问题描述】:

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

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

os.system("pwd")

os.getcwd()

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

我在网上找到了很多资源来区分上面的第三个和其他的,但是找不到太多关于上面前两个的区别。

请帮我理解这3个之间的区别,尤其是

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

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

【问题讨论】:

os.getcwd() 将目录作为字符串获取,其他的则生成pwd 进程。生成一个进程来获取目录是愚蠢的。 okie.. 你能否指出一些可以详细说明并帮助我深入理解的资源? help(os.getcwd), help(os.system), docs.python.org/2/library/os.html 好吧,os.getcwd 会得到当前的工作目录 in python 其中pwd 可以在子进程中执行不同的执行环境 or 可能不可用 or 将以需要在使用之前对其进行解码的格式给出路径。我绝对支持 Alaxander,产生一个获取工作目录的过程是愚蠢的。 【参考方案1】:

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

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

【讨论】:

我想知道,如果它可以使用 os.getcwd() 来完成,为什么我们要为其他两个提供服务?是否存在其他 2 个比 os.getcwd() 对应项更有用的特定用例? @geek_ji:确实没有理由使用os.systemsubprocess.Popen 来获得CWD。但是,您显然可以使用它们运行任意命令,因此它们对其他事情很有用。 对,os.system()process.Popen() 用于调用任意系统命令。在这种情况下,无需调用任何系统命令。 @Will:这可能有点迂腐,但我质疑您的术语“系统命令”。 os.system() 总是运行一个 shell,subprocess.Popen() 将在shell=True 运行一个 shell,所以在这些情况下他们可以运行 shell 命令——但只能运行默认 shell(UNIX 上的sh)像系统)。在任何情况下,他们都可以运行外部程序,只要该位置是可获得的。【参考方案2】:

这三个之间的主要区别在于,只有一个 os.getcwd() 可以保证工作。

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

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

【讨论】:

【参考方案3】:

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

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

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

你省略了函数popen

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

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

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

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.system("pwd") 运行一个 shell(第一个进程)来运行外部程序 pwd(第二个进程)。”所以我运行了 os.system("cat") 并在不同的终端执行了 ps -a。我可以看到 cat 的新 pid,但没有创建任何新的 shell 进程。我在这里做错了吗? @geek_ji:实现可能会有所不同,但文档说:“在 subshel​​l 中执行命令(字符串)。这是通过调用标准 C 函数 系统()。” C 函数system()(参见man 3 system)的描述明确表示“将命令传递给shell”。所以不确定ps,也许shell是execing`cat。我知道ksh 的更高版本会这样做。 strace 可能会解决这个问题 - 抱歉,我今天没有时间深入挖掘,我会尝试回到它。 @geek_ji:你让我好奇了。我会尽量深入研究这个问题,但可能不是今天。 那太好了。事实上,我想帮助这项调查。让我知道是否可以提供任何帮助。 @geek_ji:你熟悉strace吗? strace -o strace.out -f python gash.py 之类的东西(其中 gash.py 是您的脚本)。然后查看文件 strace.out(它可能很大)。我怀疑这是cat 特有的东西,所以试试pwd【参考方案4】:

偶尔会有一个令人讨厌的区别。 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

【讨论】:

以上是关于os.system("pwd") 和 os.getcwd() 的区别的主要内容,如果未能解决你的问题,请参考以下文章

[py] os.system os.popen commands 执行shell

使用 os.system("bash code") 在 Python 脚本中调用 bash 命令是一种好的风格吗? [关闭]

python 的os.system问题?

python os.system、os.popen、subprocess.Popen的区别

在Windows系统下使用pycharm调用os.system("dir")为什么乱码

Python os.system("sudo ......")需要输入密码,怎么在Python里面实现