背景
自定义一个工具包以供别人调用,出现了若干问题,现已解决并记录如下。
基本概念
1.模块(Module)
- 模块是 Python 中最小单元的可执行代码单元。
- 一个模块通常对应一个.py文件,其中包含了 Python 代码。
- 模块可以包含变量、函数、类等代码元素,提供了一种组织和重用代码的方式。
2.包(Package)
- 包是一种组织和管理模块的层次结构,用于解决命名冲突和组织代码。
- 包是一个包含
__init__.py
文件的目录,该文件的存在告诉 Python 解释器,当前目录是一个包而不是一个普通目录,文件的内容可以为空,也可以写包的初始化代码,在导入包时会执行一遍。 - 包内可以包含子模块和子包,形成一个层次结构。
示例:
my_package/
|-- __init__.py
|-- module1.py
|-- subpackage1/
| |-- __init__.py
| |-- module2.py
|-- subpackage2/
| |-- __init__.py
| |-- module3.py
3.关于 __init__.py
文件的作用
- 标识包:
__init__.py
文件的存在告诉 Python 解释器,当前目录是一个包而不是一个普通目录。 - 包的初始化: 在
__init__.py
中可以包含一些包的初始化代码,例如设置全局变量、加载模块等。 - 定义包的接口: 可以在
__init__.py
中导入其他模块或子包,并将它们暴露给外部,形成包的公共接口。这样,当用户导入包时,可以直接访问包内部的模块和功能。
4.导入(import)
在Python中导包有以下几种方式:
import aaa (as a)
from aaa import bbb (as b)
from aaa import *
(这种情况不能使用as重命名,代码中也不能使用aaa.
调用,而是直接调用)
问题解决
1.如何区分是绝对导入还是相对导入
看开头,如果是以.
开头就是相对导入,反之就是绝对导入。例如:
from package1.module1 import xxx
是绝对导入from .utils import *
是相对导入
2.相对导入表示路径方式
.
表示当前目录..
表示当前目录的父目录,以此类推- 并且支持
..model
这种先返回再进入的方式
3.什么时候用绝对导入、相对导入
执行.py文件和__init__.py
文件里使用绝对导入,模块代码里建议使用相对导入。
如果在执行.py文件中使用了相对导入,可能会报错:
from .DAG_GCN import DAG_GCN
ImportError: attempted relative import with no known parent package
- 这个错误表明 Python 解释器无法识别相对导入,因为当前模块不是在一个包内。相对导入要求模块必须位于一个包内,以便 Python 可以正确地解析相对导入的路径。所以,不要在执行文件中使用相对导入。
- 如果在模块文件中使用了相对导入,在模块中添加
if __name__ == '__main__':
也是运行不了的,除非改为绝对导入。
4.在包内部导入模块出错
这是今天遇到的主要问题,从GitHub下载了一个名为’DCGL’的工具包,直接使用IDE打开,在项目内试图调用模块并运行时,遇到了报错:
from DCGL.data import DataLoader, Simulate_Data
ModuleNotFoundError: No module named 'DCGL'
出现这种情况的原因是因为直接将’DCGL’当作了项目的根目录,导致找不到。
解决方法是,新建了一个名为’DCGL_ws’的目录,将’DCGL’目录包裹,然后再用IDE打开’DCGL_ws’,代码里就能识别到DCGL.
了。
另外一种解决方法是,去掉import语句中前面的’DCGL.',这样也能找到子模块,但如果子模块中含有相对导入的代码的话,就会报错:
from ...metrics import Metrics
ValueError: attempted relative import beyond top-level package
5.没有办法的办法
如果始终没法找到模块,有一种神奇的方法,在import之前添加下面代码就能成功导入:
import sys
# 填写实际模块的路径
sys.path.append('../')
# 打印所有python解释器可以搜索到的所有路径
print(sys.path)
参考资料
【python导包的几种方法 自定义包的生成以及导入详解】
https://blog.csdn.net/chinesepython/article/details/82113575
【Python 的模块化、相对导入、绝对导入、自定义包】
https://www.bilibili.com/video/BV1LB4y1U7dS
【第十七节4:绝对导入和相对导入】
https://www.bilibili.com/video/BV13M4y1172Y