python中_init_.py 到底有啥用?
1. __init__.py 是个啥?
__init__.py,这个文件名就是用来“初始化”的。在Python里,它主要用于标识一个目录是一个“包(Package)”。在项目里新建了一个文件夹,要让它成为一个可供导入的模块包,最简单的办法就是在里面加一个__init__.py。
比如,咱们有个项目结构如下:
my_project/ ├── __init__.py ├── module1.py └── module2.py
想要在外部使用 my_projec t这个包时,就可以这样导入:
import my_project
有了__init__.py的存在,Python才知道my_project是一个包,而不是一个普通的文件夹。所以这个文件的基本作用就是:告诉Python,“这里是个包,可以在其他地方导入我!”
2. __init__.py 还能做些啥?
1. 模块初始化操作
假如有一个需要初始化配置的工具包,可以在__init__.py里直接搞定这些初始化工作。
# 例子:my_project/__init__.py import os # 初始化配置文件路径 config_file = os.path.join(os.path.dirname(__file__), 'config.yaml') print("正在初始化配置文件……")
当一导入my_project时,config.yaml就被自动加载了。再也不用在每个子模块里重复配置路径!
2.控制子模块导入
通过在__init__.py中导入函数,可以直接在 import package_name 的时候就将所有常用的子模块或者函数导入,这样就能从包的顶级目录直接访问子模块的内容了:
3.包级别变量和函数的初始化
还可以在__init__.py里设置一些全局变量,或者定义一些包级别的工具函数。
3. __init__.py 的一些“坑”【循环导入】
什么是循环导入?
假设有两个模块module1和module2,然后在module1.py中写了这样一段代码:
# module1.py from .module2 import some_function
然后又在module2.py里这样写
# module2.py from .module1 import another_function
这就会导致Python在导入包的时候出现死循环,结果是两边互相等待对方加载,最终就会报错或者无法正常导入。
4. __init__.py 和相对导入的关系
相对导入和绝对导入
__init__.py里用相对导入的语法,比如:
from .module1 import func1
看上去没问题,但等到跑module1.py这个文件时,就会发现报错了!因为相对导入的方式要求你必须从顶层包开始导入。而你直接执行module1.py,Python根本不知道它是从哪个包里来的。
建议尽量使用绝对导入,比如这样:
from my_project.module1 import func1
这样不管是直接运行module1.py,还是导入整个my_project,都不会有问题。
5. 还有哪些小技巧?
避免复杂逻辑:不要在__init__.py中写太复杂的业务逻辑。应该是轻量级的初始化和导入,不然以后维护起来会非常麻烦。
模块导出控制:你可以用__all__来控制从包中导出哪些模块或变量。
这样当你用 from my_project import *时,Python只会导入__all__指定的内容
__all__ = ['module1', 'module2']