12.2 模块和文件

如果说模块是按照逻辑来组织Python代码的方法,那么文件便是物理层上组织模块的方法。因此,一个文件被看作是一个独立模块,一个模块也可以被看作是一个文件。模块的文件名就是模块的名字加上扩展名。py。这里我们需要讨论一些关于模块文件结构的问题。与其他可以导入类(class)的语言不同,在Python中你导入的是模块或模块属性。

12.2.1 模块名称空间

本章的后面会详细的讨论名称空间,但从基本概念来说,一个名称空间就是一个从名称到对象的关系映射集合。我们已经明确地知道,模块名称是它们的属性名称中的一个重要部分。例如string模块中的atoi()函数就是string. atoi() 。给定一个模块名之后,只可能有一个模块被导入到Python解释器中,所以在不同模块间不会出现名称交叉现象,所以每个模块都定义了它自己的唯一的名称空间。如果我在我自己的模块mymodule里创建了一个atoi()函数,那么它的名字应该是mymodule. atoi()。所以即使属性之间有名称冲突,但它们的完整授权名称(fully qualified name) ——通过句点属性标识指定了各自的名称空间——防止了名称冲突的发生。

12.2.2 搜索路径和路径搜索

模块的导入需要一个叫做“路径搜索”的过程。即在文件系统“预定义区域”中查找mymodule.py文件(如果你导入mymodule的话)。这些预定义区域只不过是你的Python搜索路径的集合。路径搜索和搜索路径是两个不同的概念,前者是指查找某个文件的操作,后者是去查找一组目录。有时候导入模块操作会失败:

12.2 模块和文件 - 图1

发生这样的错误时,解释器会告诉你它无法访问请求的模块,可能的原因是模块不在搜索路径里,从而导致了路径搜索的失败。

默认搜索路径是在编译或是安装时指定的。它可以在一个或两个地方修改。

一个是启动Python的shell或命令行的PYTHONPATH环境变量。该变量的内容是一组用冒号分割的目录路径。如果你想让解释器使用这个变量,那么请确保在启动解释器或执行Python脚本前设置或修改了该变量。

解释器启动之后,也可以访问这个搜索路径,它会被保存在sys模块的sys. path变量里。不过它已经不是冒号分割的字符串,而是包含每个独立路径的列表。下面是一个Unix机器搜索路径的样例。切记,搜索路径在不同系统下一般是不同的。

12.2 模块和文件 - 图2

这只是个列表,所以我们可以随时随地对它进行修改。如果你知道你需要导入的模块是什么,而它的路径不在搜索路径里,那么只需要调用列表的append()方法即可,就像这样:

12.2 模块和文件 - 图3

修改完成后,你就可以加载自己的模块了。只要这个列表中的某个目录包含这个文件,它就会被正确导入。当然,这个方法是把目录追加在搜索路径的尾部。如果你有特殊需要,那么应该使用列表的insert()方法操作。上面的例子里,我们是在交互模式下修改sys. path的,在脚本程序中也完全可以达到同样的目的。这里是使用交互模式执行时遇到的错误:

12.2 模块和文件 - 图4

从另一方面看,你可能有一个模块的很多拷贝。这时,解释器会使用沿搜索路径顺序找到的第一个模块。

使用sys.modules可以找到当前导入了哪些模块和它们来自什么地方。和sys.path不同,sys.modules是一个字典,使用模块名作为键(key),对应物理地址作为值(value)。