欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python的import问题:绝对路径,相对路径,sys.path.append

程序员文章站 2022-05-10 09:10:54
...

python的import问题

- 原理
在Python中,一个.py文件就称之为一个模块(Module),包含.py文件的文件夹,且里面有一个__init_.py的文件夹称为包(Package)init.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,它的模块名就是包名。在python脚本被执行,python导入其他包或模块时,python会根据sys.path列表里的路径寻找这些包或模块。如果没找到的话,程序就会报错。

>>> import sys
>>> print(sys.path)
['', 'C:\\Users\\SONG\\Anaconda3\\python37.zip', 'C:\\Users\\SONG\\Anaconda3\\DLLs', 'C:\\Users\\SONG\\Anaconda3\\lib', 'C:\\Users\\SO
NG\\Anaconda3', 'C:\\Users\\SONG\\AppData\\Roaming\\Python\\Python37\\site-packages', 'C:\\Users\\SONG\\Anaconda3\\lib\\site-packages'
, 'C:\\Users\\SONG\\Anaconda3\\lib\\site-packages\\win32', 'C:\\Users\\SONG\\Anaconda3\\lib\\site-packages\\win32\\lib', 'C:\\Users\\S
ONG\\Anaconda3\\lib\\site-packages\\Pythonwin']

程序中要导入包或模块就需要在这些路径中进行查找,分为三种情况:
① 当前执行脚本(主动执行,而不是被其他模块调用)所在路径。上面例子是在交互界面进行操作,没有执行脚本,所以为空字符串。
②python内置的标准库路径,PYTHONPATH。
③安装的第三方模块路径。

  • 分析
  • python module_0.py为前提
package_0
├── module_0.py
├── module_1.py
├── package_1
│   ├── module_2.py
│   ├── module_3.py
│   └── package_2
│       ├── module_21.py
│       └── module_22.py
└── package_3
    └── module_4.py

python module_0.py,即/home/…/package_0会被添加到 sys.path 中,可以通过该路径找到其他模块的,比如下面这些语句是不会报错的。

# module_0.py
import module_1
from package_1 import module_2
from package_1.package_2 import module_21

而下面的语句会报错:ModuleNotFoundError: No module named 'module_3’

# module_2.py
import module_3

原因:执行 python module_0.py 时,把路径(’/home/…/package_0’)添加到 sys.path 中,该路径下就不能在 module_2.py 中通过这种方式找到module_3,因为module_2.py 在路径/home/…/package_0/package_1下。

  • 绝对路径从当前执行脚本所在路径/…/需要的module
# module_2.py
from package_1 import module_3
# module_21.py
from package_1.package_2 import module_21
  • 相对路径
    单点表示引用的模块或包与当前模块在同一目录中(同一个包中)。
    两点表示在当前模块所在位置的父目录中。
# module_2.py
from . import module_3
from .package_2 import module_21
# module_21.py
from .. import module_2

下面的语句会报错:ValueError: attempted relative import beyond top-level package

# module_2.py
from ..package_3 import module_4

原因:试图在*包(top-level package)之外进行相对导入。也就是说相对导入只适用于*包之内的模块。
如果将 module_0.py 当作执行模块,则和该模块同级的 package_1 和 package_3 就是*包(top-level package),而 module_2 在package_1中,module_0、module_1和module_4都在 package_1之外,所以调用这三个模块时,就会报这个错误。
下面的语句会报错:ModuleNotFoundError: No module named ‘main.package_1’; ‘main’ is not a package

# module_0.py
from .package_1 import module_2

原因:用了相对导入的模块文件不能作为顶层执行文件,即不能 python module_0.py

  • sys.path.append
# module_2.py
sys.path.append(os.path.dirname(__file__))
import module_3
from package_2 import module_21
# module_2.py
sys.path.append(os.path.join(os.path.dirname(__file__), '../package_3'))
import module_4