main.py 和 __init__.py 的区别
一、
二、
四、
这两个文件在 Python 项目中扮演完全不同的角色,但经常让初学者困惑。
一、__init__.py
作用:把目录变成"包"
mypackage/ ├── __init__.py # 这个文件的存在,让 mypackage 成为一个"包" ├── module_a.py └── module_b.py
核心功能:
- 标识包:告诉 Python 这个目录应该被当作一个包(package)来处理
- 初始化代码:包被导入时自动执行
- 控制导入:定义
__all__,简化导入路径
示例
# mypackage/__init__.py
print("mypackage 被导入了")
from .module_a import func_a # 让用户可以直接 mypackage.func_a()
from .module_b import func_b
__all__ = ['func_a', 'func_b'] # from mypackage import * 时导出什么
使用:
import mypackage mypackage.func_a() # 不用写 mypackage.module_a.func_a()
Python 3.3+ 的命名空间包
从 Python 3.3 起,__init__.py 不是必需的(隐式命名空间包),但推荐保留,因为它能:
- 明确标识包边界
- 兼容旧版本
- 放置初始化逻辑
二、main.py
作用:程序的入口文件
project/
├── main.py # 程序从这里开始运行
├── utils.py
└── mypackage/
└── __init__.py
特点:
- 通常是顶层脚本,直接
python main.py运行 - 一般不放在包里,或者放在包里作为命令行入口
- 负责组织程序流程:解析参数、调用各模块、启动服务等
示例
# main.py
from mypackage import func_a, func_b
import argparse
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--name", default="world")
args = parser.parse_args()
func_a()
func_b()
print(f"Hello, {args.name}")
if __name__ == "__main__": # 关键:只在直接运行时执行
main()
三、对比总结
|
特性 |
|
|
|
位置 |
包目录内部 |
项目根目录(或包内作为入口) |
|
是否必需 |
Python 3.3+ 可选,但推荐 |
否(只是约定俗成) |
|
执行时机 |
包被导入时 |
手动运行 / 命令行调用 |
|
主要用途 |
标识包、初始化、控制导入 |
程序入口、组织流程 |
|
典型内容 |
|
|
|
能否多个 |
每个包一个 |
可以有多个入口脚本 |
四、__name__ == "__main__" 的关系
这是连接两者的关键概念:
- 当文件被导入时,
__name__是模块名(如mypackage) - 当文件被直接运行时,
__name__是"__main__"
所以 main.py 里常写 if __name__ == "__main__":,保证它被导入时不误执行。
五、常见项目结构
简单脚本
正规包结构
可安装的包(带命令行入口)
此时 mypackage/main.py 就是包内的入口模块。
一句话总结
__init__.py 让目录成为"包",控制导入行为;main.py 是程序入口,负责启动和调度。
两者配合:main.py 导入包 → 触发 __init__.py → 包内模块准备就绪 → main.py 调用它们运行程序。


浙公网安备 33010602011771号