python import导包路径

本文主要分析python中import文件路径的问题。

基本概念

  • module:一个.py文件
  • package:一个包含.py文件的文件夹

搜索路径

python导入其他包或者模块时,会根据sys.path中的路径进行搜索,这些路径主要为一下三种:

  1. 当前执行脚本所在路径
  2. python内置标准库路径,PYTHONPATH
  3. 安装的第三方模块路径。

import步骤

python所有加载的module信息都存放在sys.modules结构中,当import一个模块时:

  1. 如果是import A,检查sys.modules中是否有A,如果有则不加载,如果没有,则为A创建module对象,并加载A
  2. 如果是 from A import B,先为 A 创建 module 对象,再解析A,从中寻找B并填充到 A 的 __dict__

相对导入与绝对导入

绝对导入与相对导入的形式:

  • 绝对导入的格式为 import A.Bfrom A import B

  • 相对导入格式为 from . import Bfrom ..A import B,.代表当前模块,…代表上层模块,…代表上上层模块,依次类推。

顶层结构:

在没有明确指定包结构的情况下,Python 是根据 __name__ 来决定一个模块在包中的结构的:

  • 如果是 __main__ 则它本身是顶层模块,没有包结构
  • 如果是A.B.C 结构,那么顶层模块是 A。

__name__ 变量作为python的内置变量,是每个python模块必备的属性,可以取两种值:

  • 当你直接执行一段脚本的时候,这段脚本的 **name**变量等于 main
  • 当这段脚本被导入其他程序的时候,name 变量等于脚本本身的名字。

导包原则:

  1. 如果是绝对导入,一个模块只能导入自身的子模块或和它的顶层模块同级别的模块及其子模块
  2. 如果是相对导入,一个模块必须有包结构且只能导入它的顶层模块内部的模块

如果一个模块被直接运行,则它自己为顶层模块,不存在层次结构,找不到其他的相对路径,因此存在相对导入语句的模块,不能直接运行。

Python2.x 缺省为相对路径导入,Python3.x 缺省为绝对路径导入。绝对导入可以避免导入子包覆盖掉标准库模块(由于名字相同,发生冲突)。如果在 Python2.x 中要默认使用绝对导入,可以在文件开头加入如下语句:

1
from __future__ import absolute_import

from _future_ import absolute_import

这句 import 并不是指将所有的导入视为绝对导入,而是指禁用 implicit relative import(隐式相对导入), 但并不会禁掉 explicit relative import(显示相对导入)。

关于隐式相对导入、显示相对导入和绝对导入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
thing
├── books
│ ├── adventure.py
│ ├── history.py
│ ├── horror.py
│ ├── __init__.py
│ └── lovestory.py
├── furniture
│ ├── armchair.py
│ ├── bench.py
│ ├── __init__.py
│ ├── screen.py
│ └── stool.py
└── __init__.py

如果在 stool 中引用 bench,则有如下几种方式:

1
2
3
import bench # 此为 implicit relative import
from . import bench # 此为 explicit relative import
from furniture import bench # 此为 absolute import
  • 隐式相对就是没有告诉解释器相对于谁,但默认相对与当前模块;
  • 显示相对则明确告诉解释器相对于谁来导入

以上导入方式的第三种,才是官方推荐的,第一种是官方强烈不推荐的