开发环境下Flask启动流程

命令解析 -> 初始化应用实例(加载配置/组件) -> 启动WSGI服务器 -> 监听端口等待请求

阶段1. 终端命令启动时,启动命令解析
  • Click库 解析终端参数(如–host=0.0.0.0、–port=8080、–debug);
  • 读取系统环境变量(FLASK_APP/FLASK_ENV/FLASK_DEBUG等),定位应用的启动文件(如app.py)和应用实例名(如app,格式FLASK_APP=文件名:实例名);
  • 校验DEBUG模式:如果开启,会启用热重载、调试器等开发特性
    阶段2. 应用实例初始化(启动前的准备)

    创建 Flask 应用对象(app = Flask(name))

    1. 加载基础配置:默认配置(如DEBUG=False、SECRET_KEY=None)+ 自定义配置(如app.config[‘DEBUG’] = True)
    2. 初始化核心组件
  • 路由映射表(url_map):空的字典结构,用于存储@app.route()装饰的 URL 和视图函数的对应关系
  • 模板环境(Jinja2):初始化模板加载路径、过滤器、上下文处理器
  • 上下文栈(请求上下文 / 应用上下文):Werkzeug 提供的栈结构,用于管理请求生命周期
  • 扩展注册:初始化已绑定的扩展(如 Flask-SQLAlchemy)
阶段3. WSGI服务器初始化

Flask本身不实现服务器,开发环境下,核心依赖Werkzeug的WSGI服务器:

  • 把Flask应用实例(符合WSGI规范的可调用对象)传递给Werkzeug的BaseWSGIServer;
  • 绑定指定的host(默认 127.0.0.1)和port(默认 5000),创建 TCP 套接字(Socket);
  • 初始化请求处理器:Werkzeug 创建WSGIRequestHandler,用于后续解析 HTTP 请求、调用 Flask 应用处理请求。
阶段4. 启动监听循环
  • 服务器启动并进入无限监听循环:监听绑定的端口,等待客户端的TCP连接
  • 初始化信号机制:通过Blinker触发app_starting信号,执行注册的回调函数
  • 调试模式额外操作:如开启DEBUG=True,启动文件监控器,监测代码文件变化后自动重启服务器
阶段5. 服务就绪
  • 终端输出启动日志(如* Running on http://127.0.0.1:5000)
  • 此时服务器已准备就绪,可接受并处理请求(每次请求会触发Flask的请求处理流程,如路由匹配、视图函数执行、响应返回)

Flask 是典型的微框架,仅保留了核心功能:请求响应处理和模板渲染。

创建程序对象
from flask import Flask
app = Flask(__name__)  # 传入存储当前模块名称的特殊变量 __name__
模版渲染

模板(template):包含变量和运算逻辑的 HTML 或其他格式的文本。
渲染(rendering):模版中执行变量替换和逻辑计算工作的过程。
模板渲染引擎——Jinja2

常用定界符: 、、、

  • { {} } 用来标记变量
  • { % … % } 用来标记语句,比如 if 语句,for 语句等
  • {# … #} 用来写注释 、、、

templates/index.html:主页模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>'s Watchlist</title>
</head>
<body>
    <h2>'s Watchlist</h2>
    {# 使用 length 过滤器获取 movies 变量的长度 #}
    <p> Titles</p>
    <ul>
          {# 使用 endfor 标签结束 for 语句 #}
    </ul>
    <footer>
        <small>&copy; 2025 <a href="http://helloflask.com/book/3">HelloFlask</a></small>
    </footer>
</body>
</html>
请求响应处理

注册视图函数,即使用 app.route() 装饰器来为这个函数绑定对应的 URL。

from flask import Flask, render_template

app = Flask(__name__)

name = 'Grey Li'
movies = [
    {'title': 'My Neighbor Totoro', 'year': '1988'},
    {'title': 'Dead Poets Society', 'year': '1989'},
    {'title': 'A Perfect World', 'year': '1993'},
]

@app.route('/')
def index():
    return render_template('index.html', name=name, movies=movies)

render_template() 函数在调用时会识别并执行 index.html 里所有的 Jinja2 语句,返回渲染好的模板内容。在返回的页面中,变量会被替换为实际的值(包括定界符),语句(及定界符)则会在执行后被移除(注释也会一并移除)


参考