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.system
或subprocess.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:实现可能会有所不同,但文档说:“在 subshell 中执行命令(字符串)。这是通过调用标准 C 函数 系统()。” C 函数system()
(参见man 3 system
)的描述明确表示“将命令传递给shell”。所以不确定ps
,也许shell是exec
ing`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、os.popen、subprocess.Popen的区别