当前工作目录是什么?

14

我的书上写道:

在计算机上运行的每个程序都有一个当前工作目录(cwd)。任何不以根文件夹开头的文件名或路径都被认为是在当前工作目录下。

因为我用的是OSX系统,我的根文件夹是/。当我在Python shell中输入os.getcwd()时,我得到了/Users/apple/Documents。为什么我的cwd是Documents文件夹?它是否表示Python正在使用Documents文件夹?还有,每个程序的cwd都不同吗?另外,有没有任何路径可以指向以/(根文件夹)开头的Python?


这要看情况。取决于程序的启动方式。如果您进入终端,切换到“文档”文件夹并键入$ python,那么Python将以CWD为/Users/apple/Documents启动。 - deceze
cwd代表当前工作目录,就像Linux中的pwd一样。因此,os.getcwd()将会给出你正在执行它的目录名称。 - ggupta
是的,如果你问Python它的cwd是什么,并且它说它是文档目录,那么cwd就是文档目录。 - JJJ
@JJJ,这是否意味着我已经从“文档”文件夹启动了Python?如果不是,那么“文档”文件夹在cwd中的重要性是什么? - M.Hamel
你不应该知道自己从哪里开始学习Python吗? - JJJ
@JJJ,我在屏幕上有这个小文件夹!:p 但是,Documents包含所有的Python文件! - M.Hamel
5个回答

37

每个进程都有一个当前目录。当一个进程启动时,它会从其父进程继承当前目录;例如,它不会被设置为包含您正在运行的程序的目录。

如果您想了解更详细的解释,请继续阅读。

当磁盘变得足够大,您不希望将所有文件保存在同一个位置时,操作系统供应商提出了一种结构化文件的方法,即目录。因此,您可以创建新的集合以及这些集合内部的其他新集合(除了某些早期实现不能包含其他目录之外),而不是将所有内容保存在同一个目录中(或者初学者现在被教导叫做“文件夹”)。

从根本上讲,目录只是一种特殊类型的文件,其内容是其他文件的集合,也可以包括其他目录。

在原始的操作系统上,故事就到这里结束了。如果您想打印位于mine目录中的studies目录中的2021目录中的spring_semester目录中的term_paper.txt文件,您需要说:

print mine/studies/2021/spring_semester/term_paper.txt

(除非命令可能比print更神秘,目录分隔符可能是一些疯狂的东西,如方括号和冒号,或其他;

lpr [mine:studies:2021:spring_semester]term_paper.txt

但对于这篇文章来说并不重要)如果你想复制这个文件,你将不得不两次拼写整个内容:

copy mine/studies/2021/spring_semester/term_paper.txt mine/studies/2021/spring_semester/term_paper.backup

接着提出了当前工作目录的概念。假设你可以说:“从现在开始,直到我另外说明,所有我所说的文件都位于这个特定的目录中。” 因此,cd命令诞生了(除了一些旧系统,如VMS,它被称为更加笨重的名称,例如SET DEFAULT)。

cd mine/studies/2021/spring_semester
print term_paper.txt
copy term_paper.txt term_paper.backup
这就是全部。当你使用cd(或在Python中使用os.chdir())时,你会改变当前的工作目录。它会一直保留,直到你退出登录(或以其他方式退出这个进程),或者直到你通过cd切换到另一个工作目录,或者切换到另一个进程或窗口,在那里你正在运行一个具有自己独立当前工作目录的单独命令。就像你可以在不同目录下打开多个文件浏览器窗口(资源管理器、Finder或Nautilus或无论它被称为什么)一样,你也可以打开多个终端,每个终端都运行一个具有自己独立当前工作目录的shell。 因此,当你在终端中键入pwd(或cwd或者在你的命令语言中被称为什么的命令)时,结果几乎取决于你之前在该窗口或进程中所做的操作,可能还取决于你如何创建该窗口或进程。在许多类Unix系统上,当你使用关联的shell进程创建一个新的终端窗口时,它最初是在你的主目录(/home/you在许多Unix系统上,在Mac上是/Users/you,在最近的Windows上是类似于C:\Users\you的东西)中打开的,尽管可能可以配置你的终端在其他地方打开 (常见的是在某些表面上“现代”和“友好”的系统中,在你的主目录下的DesktopDocuments中)。 许多初学者对运行程序发生的情况模糊不清,心中没有完整的概念。许多人会不断地cd到包含他们的脚本或程序的任何目录中,并且当你告诉他们不需要这样做时,他们会真正感到害怕和困惑。如果frobozz/home/you/bin中,那么你就不必这样做。
cd /home/you/bin
./frobozz

因为您可以直接运行它

/home/you/bin/frobozz

如果ls/bin中,同样地你绝对不需要

cd /bin
./ls

仅仅获取一个目录列表。

此外,就像ls(或在Windows上为dir)的例子应该让你信服的那样,你运行的任何程序都将在您的当前目录中寻找文件。不是程序或脚本保存的目录。因为如果是这样的话,ls只能生成它所在的目录(/bin)的列表 - 目录列表程序、复制程序或者文字处理程序没有任何特殊之处;它们都按设计在当前工作目录中查找(尽管有些GUI程序会以您的Documents目录作为它们的当前工作目录启动,至少如果您没有告诉它们不这么做的话)。

许多初学者编写的脚本要求输入和输出文件位于特定用户主目录内的特定目录中,但这只是差劲的设计; 一个良好编写的程序将简单地在当前工作目录中查找其输入文件,除非另有指示,并将输出写入当前目录(或者如果输出由多个文件组成,则在当前目录中创建一个新目录)。

然后,Python与任何其他程序没有区别。如果在运行python时您的当前工作目录为/Users/you/Documents,则该目录是您的Python脚本或解释器中的os.getcwd()产生的结果(除非在运行时单独使用os.chdir()进入不同的目录;但同样,这可能是不必要的,通常表明脚本是由初学者编写的)。如果您的Python脚本接受一个文件名参数,则它可能应该仅仅让操作系统打开用户传递的任何东西,这意味着相对文件名是相对于调用用户的当前工作目录的。

python /home/you/bin/script.py file.txt

如果在当前目录下不存在file.txt文件,那么应该简单地使用open(sys.argv[1])并因错误而失败。让我们再说一遍; 它不会在/home/you/bin中查找file.txt - 除非这也是您,调用用户的当前工作目录,在这种情况下,您当然可以简单地编写

python script.py file.txt

顺便提一下,许多初学者不必要地尝试像这样做:

with open(os.path.join(os.getcwd(), "input.txt")) as data:
    ...

这段代码多余地调用了os.getcwd()。为什么是多余的呢?如果您一直在跟进,那么您已经知道答案了:操作系统会在当前工作目录中查找相对文件名(如此处的input.txt)。因此,您只需要:

with open("input.txt") as data:
    ...

最后一点说明。 在类Unix系统中,所有文件最终都在根目录 / 中,其中包含许多其他目录(通常普通用户不被允许在那里写任何内容,并且通常拥有执行此操作特权的系统管理员也不希望这样做)。 通过从根目录到当前目录跟踪路径,可以将每个相对文件名转换为绝对文件名。 因此,如果我们要访问的文件位于 /home/you/Documents/file.txt 中,则意味着 home 在根目录中,并包含 you,它又包含 Documents,它又包含 file.txt。 如果您的当前工作目录是 /home,则可以使用相对路径 you/Documents/file.txt 引用同一文件; 如果您的当前目录是 /home/you,则其相对路径为 Documents/file.txt(如果您的当前目录是 /home/you/Music,您可以使用 ../Documents/file.txt,但是现在让我们不再深入探讨这个例子)。

Windows 的排列略有不同,具有多个带有单字母标识符的驱动器,每个驱动器都有自己的根目录; 因此,C:驱动器的根目录是 C:\,D:驱动器的根目录是 D:\ 等(目录分隔符是反斜杠而不是斜杠,但几乎可以在任何地方使用斜杠代替它,这通常是为了保持您的理智)。


与“./”和“~/”之间的区别有什么不同?的伴随答案解释了类似的概念,重点在于相对路径和绝对路径之间的区别。 - tripleee
这个答案或多或少解决了我在阅读了数十个类似问题的答案后仍然不理解的问题。但是,我必须问一下:您对使用“文件夹”代替“目录”一词有何反对意见? - Junglemath
1
@Junglemath 感谢您的反馈 (-: 并没有强烈的反对意见,但似乎“文件夹”这个词是毫无必要地引入的,只是因为有人认为“目录”会让某些人感到焦虑。旧术语已经很好了,而现在有两个术语只会造成混淆。 - tripleee
如果您想打开一个保存在与Python脚本相同目录下的数据文件,请参阅https://dev59.com/xG855IYBdhLWcg3w-JMr。 - tripleee

13

你的Python解释器位置基于你启动它的方式,以及在启动后采取的后续操作(例如使用os模块浏览文件系统)。仅仅启动解释器会将你放置在Python安装目录下(在不同的操作系统上并不相同)。另一方面,如果你通过编辑或运行特定目录中的文件来启动它,你的位置将会是你正在编辑的文件夹。如果你需要在某个特定目录下运行解释器,并且你使用的是IDLE,最简单的方法是先创建一个Python文件,然后通过运行 > Python Shell 来打开shell,这样就已经处于该目录下了。如果你使用命令行解释器,在运行 python/python3/py 命令之前,请先导航到你想要运行解释器的文件夹中。如果你需要手动导航,你当然可以使用以下已经提到的方法:

import os
os.chdir('full_path_to_your_directory')

7

这与特定于osx没有关系,它是所有基于unix的系统共享的一个概念,我相信Windows也是如此。os.getcwd()相当于bash的pwd命令-它只是返回您所处位置的完整路径。换句话说:

alex@suse:~> cd /
alex@suse:/> python
Python 2.7.12 (default, Jul 01 2016, 15:34:22) [GCC] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.getcwd()
'/'

这取决于您从哪里启动了Python shell/script。


为什么我的cwd里有“Documents”文件夹?这是否意味着我从“Documents”文件夹启动了Python? - M.Hamel
退出shell并在操作系统shell中键入pwd。脚本/ shell的启动位置以及如何构建它取决于您要完成的任务。 - Alexander Ejbekov
当我在终端输入pwd时,得到的是/Users/apple。现在你想说什么呢? - M.Hamel
如果可能的话,您能否准确解释一下这本书的陈述本身?它似乎超出了我的理解范围。 - M.Hamel

3

Python通常(除非您正在使用虚拟环境)可以从任何目录中访问。您可以检查路径中的变量,Python应该是可用的。因此,当您询问Python时获取的目录是您开始Python时所在的目录。在启动Python之前,在您的shell中更改目录,您将看到输出会相应地发生变化。


1

os.getcwd()与OSX无关,它只是返回源文件的目录/位置。如果我的源文件在桌面上,它将返回C:\Users\Dave\Desktop\,或者说源文件保存在外部存储设备上,它可能返回类似于G:\ Programs\的内容。对于基于Unix和Windows系统来说都是一样的。


谢谢Davey!但我正在使用程序本身而不是文件!如果我使用的是文件,那么我同意你的观点,它应该给出“文档”文件夹。那么程序本身呢?它肯定不在“文档”文件夹中! - M.Hamel
在这种情况下,它取决于 Python 在您的计算机上是如何安装的。在我的计算机上,如果我从 Python 控制台运行 os.getcwd() 命令,它会返回 C:\Program Files\Python 35-32 - DaveyH-cks
1
os.getcwd() 不一定返回源文件的目录/位置。它返回当前工作目录,可能与源文件的位置相同,也可能不同。 - Bryan Oakley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接