main.py 和 __init__.py 的区别

 这两个文件在 Python 项目中扮演完全不同的角色,但经常让初学者困惑。


一、​​__init__.py​

作用:把目录变成"包"

​

mypackage/
├── __init__.py      # 这个文件的存在,让 mypackage 成为一个"包"
├── module_a.py
└── module_b.py

  

核心功能:

  1. 标识包:告诉 Python 这个目录应该被当作一个包(package)来处理
  2. 初始化代码:包被导入时自动执行
  3. 控制导入:定义 __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

  


特点:

  1. 通常是顶层脚本,直接 python main.py 运行
  2. 一般不放在包里,或者放在包里作为命令行入口
  3. 负责组织程序流程:解析参数、调用各模块、启动服务等

示例

# 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()

  


三、对比总结

特性

​__init__.py​

​main.py​

位置

包目录内部

项目根目录(或包内作为入口)

是否必需

Python 3.3+ 可选,但推荐

否(只是约定俗成)

执行时机

包被导入时

手动运行 / 命令行调用

主要用途

标识包、初始化、控制导入

程序入口、组织流程

典型内容

​from .x import y​​​, ​​__all__​

​if __name__ == "__main__":​

能否多个

每个包一个

可以有多个入口脚本


四、​​__name__ == "__main__"​​ 的关系

这是连接两者的关键概念:

# mypackage/__init__.py 里也可以写:
if __name__ == "__main__":
    print("直接运行 __init__.py")

  

  • 当文件被导入时,__name__ 是模块名(如 mypackage
  • 当文件被直接运行时,__name__"__main__"

所以 ​​main.py​​ 里常写 ​​if __name__ == "__main__":​​,保证它被导入时不误执行。


五、常见项目结构

简单脚本

project/
├── main.py
├── utils.py
└── config.py

  

正规包结构

project/
├── main.py              # 入口
├── requirements.txt
└── mypackage/
    ├── __init__.py
    ├── core.py
    ├── utils.py
    └── cli.py

  

可安装的包(带命令行入口)

# pyproject.toml
[project.scripts]
myapp = "mypackage.main:main"

  

此时 ​​mypackage/main.py​​ 就是包内的入口模块。


一句话总结

​__init__.py​​​ 让目录成为"包",控制导入行为;​​main.py​​ 是程序入口,负责启动和调度。

两者配合:​​main.py​​ 导入包 → 触发 ​​__init__.py​​ → 包内模块准备就绪 → ​​main.py​​ 调用它们运行程序。

 




微信图片_20260323111806_89_204

 


posted @ 2026-09-17 11:59  程序员食堂  阅读(0)  评论(0)    收藏  举报