文件查找与当前工作目录的切换

在执行python hello.py时,大家有可能会看到终端上显示出错误:

$ python hello.py
python: can't open file 'hello.py': [Errno 2] No such file or directory.

这和Python解释器的文件查找机制有关。

大家还记得先前提到的“当前工作目录”的概念吗。不记得了可以跳回2.2节去看一眼:终端会在提示符里面显示当前的工作目录。 而当你键入python hello.py时,Python解释器会在当前的工作目录里去找hello.py并执行。 而如果你当前工作目录下没有hello.py文件时,Python解释器就会报错了。

举个错误的例子:假设你有一个文件夹叫做C:\SICP,并且你把我们下发的实验材料的压缩包解压在了这个文件夹中,也就是说你的实验材料都在C:\SICP\lab00下。 但是你打开终端的时候,默认的当前工作目录可能是C:\User\Dell(在你的电脑上可能是其它工作目录),而现在你知道hello.pyC:\SICP\lab00\code目录下,那么当你执行:

C:\User\Dell> python hello.py

就会出现问题。但如果你当前的工作目录是C:\SICP\lab00\code,那么你执行:

C:\SICP\lab00\code> python hello.py

就不会有任何问题。那么接下来你就会问,该如何改变当前的工作目录呢?你可以通过cd这个命令切换终端的当前工作目录!

cd的全称是change directory。

一方面,你可以通过cd后跟一个目录的“绝对路径”来把工作目录切换成“绝对路径”所表示的目录。 比如在上面的例子中,如果你当前的工作目录是C:\User\Dell,那么你可以像下面这样切换当前的工作目录到C:\SICP\lab00\code

C:\User\Dell> cd C:\SICP\lab00\code
C:\SICP\lab00\code>

什么是绝对路径?像C:\SICP\lab00\code以盘符(C盘的盘符叫做C:,D盘的盘符叫做D:,以此类推)开头的路径,就叫做绝对路径。否则叫相对路径。

在macOS和Linux中并不存在“盘符”的概念,在这些操作系统中,最底层的文件夹叫做“根目录”(/,也就是“root”),以/开头的路径叫做绝对路径,如/home/user/sicp/lab00/code

你可能会注意到,Windows上路径的目录之间使用\分割,而macOS和Linux则使用/分割。

另一方面,你也可以通过cd后跟一个目录的“相对路径”来把工作目录切换成“相对路径”所表示的目录。 比如,如果你当前的工作目录为C:\SICP\lab00,并且这个目录下还有一个code目录,那么你可以像这改变当前的工作目录:

C:\SICP\lab00> cd code
C:\SICP\lab00\code>

这里的code就是相对路径。这个过程就很像你在资源管理器的lab00目录下双击了code目录,然后就进入了lab00\code目录一样。 如果你的C:\SICP\lab00下没有code目录,那么终端上就会显示错误。你可能需要打开资源管理器看看是怎么回事。

接下来你可能会想知道如何回到上一级目录或者切换磁盘。下面是一些演示:

  • ..的含义为上一级目录。.的含义为当前目录。可以使用cd a\b\c这样的形式一口气进入多层目录(a\b\c就是所谓的相对路径)。
    C:\SICP\lab00\code> cd ..      # 进入上层目录
    C:\SICP\lab00> cd ..           # 再次进入上层目录
    C:\SICP> cd lab00\code         # 进入lab00目录下的code目录
    C:\SICP\lab00\code> cd ..\..   # 进入上层目录的上层目录
    C:\SICP> cd .\lab00            # 进入当前目录的lab00目录
    C:\SICP\lab00> cd ..\lab00     # 进入上层目录的lab00目录 (即还是当前目录)
    C:\SICP\lab00>
    
  • 在Windows上,如果当前目录的盘符与目标目录的盘符不同,你首先需要通过"{盘符}:"命令切换盘符。
    C:\SICP\lab00> cd D:\NJU    # 无效的切换
    C:\SICP\lab00> D:           # 有效的切换
    D:\NJU>
    
  • 一般来说,Windows的路径不区分大小写,macOS和Linux是否区分取决于你安装系统时的选择。

当前工作目录下的有哪些目录与文件?(可选)

你可以通过dir命令(在Windows上)或ls命令(在macOS和Linux上)显示当前目录下的文件。

例如,在Windows下:

C:\SICP\lab00\code>dir
 驱动器 C 中的卷是 Windows
 卷的序列号是 4C0F-CDB0

C:\SICP\lab00\code 的目录

2020/09/21  10:37    <DIR>          .
2020/09/21  10:37    <DIR>          ..
2020/09/21  15:03                19 hello.py
2020/09/19  17:48               480 lab00.py
            2 个文件            499 字节
            3 个目录 100,005,732,352 可用字节

在macOS和Linux下:

~\SICP\lab00\code$ ls
hello.py lab00.py

命令的格式(可选)

现在,大家应该已经执行过很多命令了。 接下来,我们带好奇的同学总结一下命令的通用格式是什么样的。

一般来说,命令的格式如下:

$ executable [-option [parameter]]... [positional-parameter]...

其中:

  • executable是一个可执行文件,比如在命令python --version中,executable就是python——它正是我们在第一节配置Python环境中所下载的可执行文件。
  • [-option [parameter]]...的中括号表示“可选”,省略号表示零个或多个。 它们加起来的意思是,executable后面可以跟零个或多个形如-option [parameter]这样的东西,其中-option代表一个选项, -option [parameter]代表选项后面可以跟一个可选的parameter,这视具体的选项而定——有的选项需要parameter,有的就不需要。 - [positional-parameter]...代表零个或多个positional-parameter。 这种positional-parameter与-option parameter中parameter的区别是,它不会跟在选项后面。

下面举几个例子就容易理解了:

  • python --version这个命令中,--version就是一个形如-option的选项——这个选项的意思是叫python这个可执行程序打印它的版本号。 此外,--version后面不需要跟parameter。
  • cd C:\SICP\lab00这个命令中,cd概念上也是一个可执行文件。而且它后面没有任何形如-option [parameter]这样的东西。 但是有一个绝对路径C:\SICP\lab00作为positional-parameter。这表示把当前的目录切换到C:\SICP\lab00
  • python lab00.py这个命令中,没有任何形如-option [parameter]这样的东西。但是有个positional-parameter——lab00.py。 这个命令表示启动Python解释器去执行lab00.py里的代码。
  • python -i lab00.py这个命令中(将在4.3节出现),有一个-i选项。注意,这里的lab00.py不是-i的parameter,而是positional-parameter——因为-i选项后不需要parameter。 在多了一个-i选项后,这个命令就比前面讲解的python lab00.py多了些功能——除了要像python lab00.py一样启动Python解释器去执行lab00.py里的代码, 还要让Python解释器执行完毕后进入交互模式,而不是直接退出Python解释器。
  • python -m doctest lab00.py这个命令中(将在4.3节出现),有一个-m选项。在这里,doctest确实是-m的parameter。 回顾一下,-m doctest是一个形如-option [parameter]的东西。另外,这里的lab00.py依旧是positional-parameter。 在多了一个-m doctest后,这个命令比起前面两个命令的含义又产生了变化——Python解释器要启动doctest模块去执行lab00.py里的doctest。

此外,-option一般有两种约定俗成的形式:

  • 一种是像--version这样的由两个连字符加上一个单词的形式。这种形式长得很“长”,方便理解。
  • 一种是像-i这样的由一个连字符加上字母(一般是某个单词的首字母)的形式。这种形式长得很“短”,方便输入。