4-1-模块-宏伟蓝图

模块是最高级别的程序组织单元,它将程序代码和数据封装起来以便重用。

每一个文件都是一个模块,并且模块导入其他模块之后就可以使用导入模块定义的变量名。

模块可以由两个语句和一个重要的内置函数进行处理:

  • **import:**使客户端(导入者)以一个整体获取一个模块。
  • **from:**允许客户端从一个模块文件中获取特定的变量名。
  • **imp.reload:**在不中止 Python 程序的情况下,提供了一个种重新载入模块文件代码的方法。

1. Import 如何工作

程序第一次导入指定文件时,会执行三个步骤:

    1. 找到模块文件。
    1. 编译成位码(需要时)。
    1. 执行模块的代码来创建其所定义的对象。

这三个步骤只在程序执行时,模块第一次导入时才会进行。在这之后,导入相同模块时,会跳过这三个步骤,而只提取内存中已加载的模块对象。

2. 模块搜索路径

Python 的模块搜索路径是以下主要组件组合而成的结果:

  1. 程序的主目录。
  2. PYTHONPATH 的目录(如果已经进行了设置)。
  3. 标准链接库目录。
  4. 任何 .pth 文件的内容(如果存在的话)。
  5. 第三方扩展的 site-packages 主目录。

2.1 配置搜索路径

搜索路径的 PYTHONPATH 和路径文件部分允许我们调整导入查找文件的地方。
在 Windows 上,把 PYTHONPATH 设置为分号隔开的一串目录:

1
c:\pycode\utilities;d:\pycode\package1

或者创建一个名为 pydirs.pth 的文本文件,其内容如下所示:

1
2
c:\pycode\utilities
d:\pycode\package1

2.2 sys.path 列表

可以通过打印内置的 sys.path 列表查看模块搜索路径在机器上的实际配置。

2.3 模块文件选择

Python 会选择在搜索路径中第一个符合导入文件名的文件。

模块来源

import b 形式的 import 叙述可能会加载:

  • 源代码文件 b.py
  • 字节码文件 b.pyc。
  • 目录 b,包导入。
  • 编译扩展模块(通常用 C 或 C++ 编写),导入时使用动态连接(例如,Linux 的 b.so 以及 Cygwin 和 Windows 的 b.dll 或 b.pyd)。
  • 用 C 编写的编译好的内置模块,并通过静态连接至 Python。
  • ZIP 文件组件,导入时会自动解压缩。
  • 内存内映像,对于 frozen 可执行文件。
  • Java 类,在 Jython 版本的 Python 中。
  • .NET 组件,在 IronPython 版本的 Python 中。

import hooks 和 ZIP 文件
重新定义 Python 中 import 操作所做的事也是可能的,也就是使用 import hook。这些 hook 可以让 import 做各种有用的事,例如,从归档中加载文件,执行解密等。

Python 使用这些 hook 让文件可以直接从 ZIP 文件中导入,归档后的文件会在导入时自动解压缩。

最佳化字节码文件

Python 也支持最佳化字节码文件 .pyo,这种文件在创建和执行时要加上 -O 这个 Python 标志位。因为这些文件执行时会比普通的 .pyc 文件快一点,然而,它们并没有频繁地使用。

1