1. __init__.py 什么时候会执行?
__init__.py 的执行时机非常明确:当它的父级文件夹被当作一个"包(Package)"被第一次导入时,这个文件里的代码就会自动执行。
- 具体场景 :当你写
from app import create_app或者import app时。 - 触发动作 :Python 解释器会先进入
app/文件夹,找到并执行 里面的__init__.py文件中的所有代码,最后把定义好的变量(比如create_app)返回给你。 - 一句话理解 :它是整个包(也就是你的核心业务目录
app/)的"初始化脚本"。
2. 放到其他的文件里面可以吗?
绝对不可以。
- Python 语言层面 :
__init__.py是 Python 语言规定的特殊文件名。它的名字是固定死的,叫作"包初始化文件"。你把它改名叫init.py、start.py或者main.py,放在app/文件夹下,它就失去了作为"包入口"的魔法功能,变成了普通的模块文件。 - 项目架构层面 :即使你在别的文件(比如
routes/main.py)里也写了类似的函数,那也无法触发app/整个包的初始化流程。
3. 怎么放到 __init__.py 这里比较好?
在 Flask 的企业级项目中,把**应用工厂函数(create_app)放在 app/__init__.py 是公认的"黄金位置"。这样做有以下几个极佳的理由:
-
符合"初始化"的语义 :
app/文件夹是你的项目核心应用包。当这个包被导入时,它理应完成自身的初始化(创建实例、加载配置、注册插件、注册蓝图)。__init__.py完美承载了"初始化"的职责。 -
让启动文件(入口)保持干净:把你的业务逻辑全部封装在 app/包里,然后在项目根目录的启动文件(通常叫 run.py
或 app.py)中,只需要写极少的代码:
python# run.py from app import create_app # 触发 app/__init__.py 执行,拿到工厂函数 app = create_app() if __name__ == '__main__': app.run(debug=True)这样,项目的入口文件就只有一个作用:启动项目。所有的脏活累活(初始化、配置、插件绑定)都被封装在 app/init.py
内部了。
-
方便测试和部署 :工厂函数
create_app()可以接收参数(比如create_app(config_class=TestConfig))。在单元测试或不同服务器部署时,你只需要在测试脚本或部署配置里调用create_app(不同配置)即可,极其灵活。
总结
一般的项目结构应该是这样的:
text
项目根目录/
├── run.py <-- 唯一的启动入口,代码极少
├── config.py <-- 存放不同的配置类
└── app/ <-- 核心业务包
├── __init__.py <-- 【核心】应用工厂函数,负责初始化一切
├── routes/
│ ├── __init__.py
│ ├── main.py <-- 首页等路由
│ └── user.py <-- 用户相关路由
└── templates/
└── index.html
照这个标准结构搭下来,Flask 项目就具备了企业级的骨架。