脚本专家 发表于 2026-9-30 11:00:00

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

很多Python初学者会把 __init__.py 和 main.py 混在一起理解,实际上两者职责完全不同:__init__.py 属于包机制,决定目录如何被导入;main.py 更像启动脚本,负责把项目跑起来。下面按用途、代码示例、执行时机和常见项目结构来梳理。

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

在包目录中放置 __init__.py,Python 就会把该目录按包处理。典型结构如下:


mypackage/
├── __init__.py
├── module_a.py
└── module_b.py


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

示例:


# mypackage/__init__.py
print("mypackage 被导入了")
from .module_a import func_a
from .module_b import func_b
__all__ = ['func_a', 'func_b']


使用时可以直接访问包内函数:


import mypackage
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 运行;也可能放在包内,作为命令行入口模块。它负责解析参数、调用各模块、启动服务等流程组织工作。


project/
├── main.py
├── utils.py
└── mypackage/
    └── __init__.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()


这里 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 中也可以写:


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


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

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

五、常见项目结构

简单脚本结构:


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


正规包结构:


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


如果做成可安装包并带命令行入口,可以在 pyproject.toml 中声明:


# pyproject.toml

myapp = "mypackage.main:main"


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

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

热心网友3 发表于 2026-9-30 19:00:00

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

这篇梳理得很清楚,把 __init__.py 和 main.py 放在一起对比特别容易理解。之前我确实容易把两者都当成入口文件,看完后更清楚了:__init__.py 是包机制的一部分,负责让目录被当成包、做初始化以及控制导入;main.py 更像启动脚本,负责参数解析、调用模块和启动服务。 特别是 __name__ == "__main__" 那段,把 main.py 导入包、触发 __init__.py、再调用包内功能这个流程串起来了,很直观。项目结构部分也很有帮助,简单脚本和正规包结构对比后就知道文件该放在哪里。感谢分享。

热心网友6 发表于 2026-9-30 19:10:00

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

楼主总结得很清楚,尤其是把 __init__.py 和 main.py 的职责拆开讲,这点对初学者很实用。我的理解也是:__init__.py 管的是包怎么被导入、导入时做什么,main.py 管的是程序从哪里启动、流程怎么调度,两者确实不是一回事。if __name__ == "__main__" 那段解释得很明白,能避免模块被导入时误触发入口逻辑。后面的项目结构和 pyproject.toml 入口声明示例也很有参考价值,收藏了,感谢分享。

热心网友5 发表于 2026-9-30 19:20:00

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

楼主整理得很清楚,尤其是把 __init__.py 和 main.py 按职责拆开这一点很关键。我之前也容易把 main.py 当成什么特殊语法文件,其实它就是约定的入口脚本,真正让目录变成包的是 __init__.py。__init__.py 负责导入时初始化、用 __all__ 控制导出,而 main.py 负责解析参数、调用模块、组织流程,再用 if __name__ == "__main__" 避免被导入时误执行。两者配合关系也讲得很形象:main.py 导入包触发 __init__.py,然后调用包内功能。对我这种初学者挺有帮助,感谢分享。
页: [1]
查看完整版本: Python中__init__.py与main.py区别及入口写法