查看: 154|回复: 0

Python中__init__.py与main.py区别及入口写法

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
很多Python初学者会把 __init__.py 和 main.py 混在一起理解,实际上两者职责完全不同:__init__.py 属于包机制,决定目录如何被导入;main.py 更像启动脚本,负责把项目跑起来。下面按用途、代码示例、执行时机和常见项目结构来梳理。

一、__init__.py:让目录成为Python包

在包目录中放置 __init__.py,Python 就会把该目录按包处理。典型结构如下:
  1. mypackage/
  2. ├── __init__.py
  3. ├── module_a.py
  4. └── module_b.py
复制代码

它主要有三个作用:标识包,告诉Python这个目录应作为package;执行初始化代码,包被导入时自动运行;控制导入,通过 __all__ 简化导入路径。

示例:
  1. # mypackage/__init__.py
  2. print("mypackage 被导入了")
  3. from .module_a import func_a
  4. from .module_b import func_b
  5. __all__ = ['func_a', 'func_b']
复制代码

使用时可以直接访问包内函数:
  1. import mypackage
  2. mypackage.func_a()
复制代码

因为 __init__.py 中已经执行了 from .module_a import func_a,所以不必写成 mypackage.module_a.func_a()。__all__ 则决定 from mypackage import * 时导出哪些名字。

从 Python 3.3 开始,__init__.py 对命名空间包来说不是必需的,但实际项目仍推荐保留。原因包括:明确标识包边界、兼容旧版本、在包导入时放置初始化逻辑。

二、main.py:程序入口与流程调度

main.py 通常位于项目根目录,直接通过 python main.py 运行;也可能放在包内,作为命令行入口模块。它负责解析参数、调用各模块、启动服务等流程组织工作。
  1. project/
  2. ├── main.py
  3. ├── utils.py
  4. └── mypackage/
  5.     └── __init__.py
复制代码

一个常见写法是:
  1. # main.py
  2. from mypackage import func_a, func_b
  3. import argparse
  4. def main():
  5.     parser = argparse.ArgumentParser()
  6.     parser.add_argument("--name", default="world")
  7.     args = parser.parse_args()
  8.     func_a()
  9.     func_b()
  10.     print(f"Hello, {args.name}")
  11. if __name__ == "__main__":
  12.     main()
复制代码

这里 if __name__ == "__main__" 的作用是:只有直接运行 main.py 时才执行 main();如果 main.py 被其他模块导入,则不会误触发程序流程。

三、两者对比

__init__.py:位于包目录内部;Python 3.3+ 可选但推荐保留;在包被导入时执行;用于标识包、初始化、控制导入;典型内容是 from .x import y 和 __all__;每个包一个。

main.py:通常位于项目根目录,也可放在包内作为入口;不是语法必需,更多是约定;手动运行或命令行调用时执行;用于程序入口和组织流程;典型内容是 if __name__ == "__main__":;项目可以有多个入口脚本。

四、__name__ == "__main__" 的连接作用

这是理解两者的关键概念。__init__.py 中也可以写:
  1. # mypackage/__init__.py 里也可以写:
  2. if __name__ == "__main__":
  3.     print("直接运行 __init__.py")
复制代码

当文件被导入时,__name__ 是模块名,例如 mypackage;当文件被直接运行时,__name__ 是 "__main__"。所以 main.py 常写 if __name__ == "__main__":,保证它作为模块被导入时不执行入口逻辑。

配合关系可以概括为:main.py 导入包,触发 __init__.py,包内模块准备就绪,然后 main.py 调用它们运行程序。

五、常见项目结构

简单脚本结构:
  1. project/
  2. ├── main.py
  3. ├── utils.py
  4. └── config.py
复制代码

正规包结构:
  1. project/
  2. ├── main.py
  3. ├── requirements.txt
  4. └── mypackage/
  5.     ├── __init__.py
  6.     ├── core.py
  7.     ├── utils.py
  8.     └── cli.py
复制代码

如果做成可安装包并带命令行入口,可以在 pyproject.toml 中声明:
  1. # pyproject.toml
  2. [project.scripts]
  3. myapp = "mypackage.main:main"
复制代码

此时 mypackage/main.py 就是包内的入口模块,main 函数作为命令入口被调用。

一句话总结:__init__.py 让目录成为包,并控制导入行为;main.py 是程序入口,负责启动和调度。两者不是替代关系,而是入口脚本与包初始化机制之间的配合关系。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-30 12:26 , Processed in 0.020111 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部