python中的包和导入
python使用包(package)、模块(module)来组织代码,以便于维护和管理。
使用关键字import来导入模块。导入要指定搜索路径,即从何处搜索模块。
Python搜索模块路径是由四部分构成的:
- 程序的主目录: 执行文件的目录,即
__main__
文件的目录。 - PATHONPATH目录:环境变量,可以设置或扩展它。
- 标准目录:DLLS, Lib, site-packages目录。
- .pth文件的目录: 可以放在python安装目录或site-packages中。每行一个路径
最后这4部分的路径都存储在sys.path列表中。
因此也可以在代码中使用sys.path.add(“/path/to/module”)来添加自定义搜索路径。
导入基础
实验环境:python3.9.2 windows
1 | import PACKAGE OR MODULE [as ALIAS] |
考虑如下的结构:
在main中import sub时打印打sub:
1 | <module 'sub' (namespace)> <class 'module'> |
可见package也是一种module,只是标识为namespace了。
绝对导入和相对导入
- 绝对导入:当从sys.path路径去搜索模块时,称为绝对导入。
比如,import sys
,import os
。
执行sub_main.py,如果我们要导入上级目录的top.py,那么需要把top所在的目录添加到sys.path中。
1 | # sub_main.py |
绝对导入简单清晰明了。
- 相对导入
形如:
1 | from . import x |
相对导入能避免一些包路径更改引入的大量绝对路径修改的麻烦。
相对导入有一个很重要的限制,就是相对路径不是一个顶层包,即__name__属性为__main__的顶层模块所在的目录
1 | # main.py |
main 导入sub2
sub2.py 有如下导入情境:
1 | # sub2.py |
__init__.py
当导入一个模块时(不管这个模块是包还是普通模块),包中的__init__.py
文件会被自动导入。该文件可以用来做一些模块的初始化,控制import *
的行为,简化外部导入,但有很多说法,只有目录下包含一个__init__.py
文件才是一个包,我觉得是不对的。至少我自己使用中不是这样的。__init__.py
只是一个会自动执行的普通py文件
考虑在main中导入sub_sub.py文件:
1 | # main.py |
import, importlib
import
关键字是__import__函数的语法糖,在动态导入中推荐使用importlib而不是直接使用__import__。
1 | import importlib |
python中的包和导入