Flask 版本演进全解:从 CHANGES.rst 读懂 Flask 从 0.1 到 3.2 的关键变更与升级要点
本文以仓库中的 CHANGES.rst 为主体,系统梳理 Flask 自 2010 年首个公开预览版 0.1 到当前开发版 3.2.0.dev 的全部版本脉络:每个大版本周期引入了哪些核心能力、废弃并移除了哪些 API、依赖最低版本如何演进。读完后,你可以快速判断自己的项目应升级到哪个版本、升级时要迁移哪些代码,并从源码层面验证每项变更的真实行为。
CHANGES.rst 在仓库中的定位与阅读方法
CHANGES.rst 是 Flask 的完整变更日志,采用 ReStructuredText 格式,按版本倒序排列,当前覆盖 0.1(2010-04-16)至 3.2.0(Unreleased)共 40 余个版本条目。每条变更记录通常附带三类引用:
:pr:表示合并的 Pull Request 编号;:issue:表示对应的 Issue 编号;:ghsa:表示 GitHub Security Advisory 编号(如 3.1.1 中的:ghsa:4grg-w6v8-c28g`),出现该标记的条目通常是安全修复,升级时应优先关注。
从仓库构建配置看,pyproject.toml 中 [tool.flit.sdist] 显式将 CHANGES.rst 打包进源码发行版(sdist),说明它是官方发行物的一部分,文档站点中的 changes 页面 也由此生成。因此,将本文件作为“升级前的权威核对清单”使用是可靠的:仓库当前版本号为 3.2.0.dev(pyproject.toml 第 3 行),即 3.2.0 条目尚未发布,其中的行为变更在正式发布前可能微调。
3.x 系列:现代化重构与安全加固(当前主线)
3.0.0(2023-09-30):Sans-IO 架构与旧代码清除
3.0.0 是架构层面的一次大版本,核心变更包括:
- 移除此前所有已废弃的代码;
- 将代码重构为 Sans-IO 基础类:
Flask与Blueprint类获得了 Sans-IO 基类,IO 相关行为被拆分出来,这一结构在仓库中体现为 src/flask/sansio/ 目录,其中的app.py、blueprints.py、scaffold.py与具体 IO 类分离,便于 Quart 等 ASGI 框架复用同一套路由/蓝图逻辑; __version__属性被标记废弃,官方建议改用特性检测或importlib.metadata.version("flask")获取版本;url_for允许self作为参数;- 要求 Werkzeug >= 3.0.0。
仓库中 src/ 下已找不到任何 __version__ 定义,与该废弃决定一致。
3.1.0(2024-11-13):安全与资源限制增强
3.1.0 是 3.x 中信息量很大的一个功能版本,主要变更:
- 放弃 Python 3.8 支持;依赖最低版本提升为 Werkzeug >= 3.1、ItsDangerous >= 2.2、Blinker >= 1.9;
- 新增
PROVIDE_AUTOMATIC_OPTIONS配置,控制是否自动响应OPTIONS请求; open_resource/open_instance_resource/Blueprint.open_resource新增encoding参数(默认utf-8);Request.max_content_length支持按请求定制,而不再只能通过MAX_CONTENT_LENGTH全局配置;新增MAX_FORM_MEMORY_SIZE与MAX_FORM_PARTS配置;- 支持
Partitionedcookie 属性(CHIPS),对应SESSION_COOKIE_PARTITIONED配置; - 新增
SECRET_KEY_FALLBACKS密钥轮换 配置:一个旧密钥列表,仍可用于验证(unsign)旧会话。
从源码可以验证密钥轮换的实现:src/flask/sessions.py 中 SecureCookieSessionInterface.get_signing_serializer 先把 app.config["SECRET_KEY_FALLBACKS"] 展开进密钥列表,再把当前 app.secret_key 追加到末尾——注释明确说明 “itsdangerous expects current key at top”(当前密钥排在首位以便签名时使用)。该配置默认值为 None,定义在 src/flask/app.py。
flask run的-e path优先于默认.env/.flaskenv文件;load_dotenv默认同时加载默认文件,除非传入load_defaults=False;- 修复
host_matching=True或subdomain_matching=False与SERVER_NAME的交互问题:设置SERVER_NAME不再把请求限制在该域名内; - 新增
TRUSTED_HOSTS配置,Request.trusted_hosts在路由阶段进行检查。
3.1.1(2025-05-13):安全修复
3.1.1 的关键条目是使用 SECRET_KEY_FALLBACKS 时签名密钥选择顺序的修复(:ghsa:4grg-w6v8-c28g)。如果你从 3.1.0 直接跳版本,注意 3.1.0 的密钥轮换存在该缺陷,**应直接升级到 3.1.1 或更高版本**。其余条目:cli_runner.invoke 类型提示修复、flask --help` 先加载应用与插件以保证显示全部命令。
3.1.2(2025-08-19)
stream_with_context在异步视图中不再失败;- 测试客户端使用
follow_redirects时,最终session状态正确; send_file传入 bytes IO 的类型提示放宽。
3.1.3(2026-02-18)
- 对只访问键而不访问值的操作(如
in、len),session 也会被标记为“已访问”(:ghsa:68rp-wp8r-4726)。这条修复影响Vary: Cookie头:此前对session` 做成员判断不触发 cookie 头变化,修复后行为与“读取”一致。
3.2.0(Unreleased):上下文合并与行为修正
3.2.0 是仓库中正在开发的主线版本(pyproject.toml 版本号为 3.2.0.dev),已记录的变更包括:
- 放弃 Python 3.9 支持(当前 pyproject.toml 中
requires-python = ">=3.10"已生效); - 移除此前已废弃的
__version__; RequestContext与AppContext合并:RequestContext成为废弃别名;已存在的 app context 在分派请求时不会被复用。源码中可以看到合并后的处理逻辑——src/flask/ctx.py 保留了一个模块级__getattr__,在访问RequestContext名称时给出 “'RequestContext' has merged with 'AppContext'” 的废弃提示;- 参与请求分派的众多
Flask方法改为把当前AppContext作为第一个参数,而非使用代理对象;子类若重写了这些方法,旧签名会被检测到并给出废弃警告,在废弃期内继续可用; - 即使某个 teardown 回调抛出异常,所有 teardown 回调仍会被调用;
should_ignore_error方法被废弃,建议改在 teardown 处理函数中处理错误。src/flask/app.py 中可以看到对覆写旧方法的检测与警告逻辑;template_filter、template_test、template_global装饰器可以不带括号使用;redirect默认状态码从 302 改为 303:303 指示客户端无论原请求是 GET 还是 POST 都切换为 GET,兼容 HTMX 等前端库。源码中两处签名均已确认:src/flask/helpers.py 的redirect(location, code: int = 303, ...)与 src/flask/sansio/app.py 的Flask.redirect(self, location, code: int = 303);- 新增按视图粒度启用自动 OPTIONS 的能力:即使配置层面禁用了
PROVIDE_AUTOMATIC_OPTIONS(默认值为True,见 src/flask/app.py,分派时检查位于 src/flask/sansio/app.py),仍可为单个视图显式开启; Flask.select_jinja_autoescape的文件扩展名比较改为大小写不敏感。
2.x 系列:从 Python 2 中彻底走出
2.3.x:废弃代码的大清除
2.3.0(2023-04-25)放弃 Python 3.7 支持,并移除了大量旧代码,这份清单是升级 2.x 项目的核心核对表:
FLASK_ENV环境变量、ENV配置键、app.env属性移除;session_cookie_name、send_file_max_age_default、use_x_sendfile、propagate_exceptions、templates_auto_reload等app上的属性移除,改为直接读配置键;JSON_AS_ASCII、JSON_SORT_KEYS、JSONIFY_MIMETYPE、JSONIFY_PRETTYPRINT_REGULAR配置键移除;app.before_first_request/bp.before_app_first_request装饰器移除;json_encoder/json_decoder属性与json.JSONEncoder/JSONDecoder类移除;json.htmlsafe_dumps/htmlsafe_dump移除;- 蓝图注册后再调用其 setup 方法从“警告”变为直接报错。
同时 2.3.0 引入的替代性变更:escape 和 Markup 应直接从 markupsafe 导入(flask 中的导出被标记废弃);信号永远可用,blinker>=1.6.2 成为必需依赖,signals_available 属性废弃;信号支持 async 订阅函数;打包改用 pyproject.toml(setup.cfg 移除);空名称的蓝图直接抛 ValueError;SESSION_COOKIE_DOMAIN 不再回退到 SERVER_NAME。
后续的 2.3.1 恢复了被误删的 from flask import Markup,2.3.2/2.3.3 则修复了访问 session 时设置 Vary: Cookie 头、Python 3.12 兼容以及应用根路径/实例路径的确定逻辑(2.3.3 还换用 flit_core 作为构建后端——这正是当前仓库 pyproject.toml 中 build-backend = "flit_core.buildapi" 的来源)。
2.2.0(2022-08-01):JSON 提供者与上下文变量
2.2.0 是 2.x 中变更密度最高的版本:
- 上下文管理重构:应用与请求上下文改用 Python 原生
contextvars管理,取代 Werkzeug 的LocalStack,带来性能与内存收益;_app_ctx_stack.top与_request_ctx_stack.top被标记废弃,扩展作者被要求把数据存到g上(如g._extension_name_attr); - JSON 行为收敛到
app.json提供者:flask.url_for会调用app.url_for,flask.abort调用app.aborter(可用Flask.aborter_class/make_aborter定制),flask.redirect调用app.redirect,flask.jsonify调用app.json.response——这为“按应用定制全局行为”提供了正式入口,对应的 JSON 实现位于 src/flask/json/; before_first_request废弃,建议在建应用时执行初始化代码;- CLI 增强:
flask命令新增--app与--debug选项、--env-file指定 dotenv 文件;自定义 CLI 命令不再需要@with_appcontext装饰(应用上下文已自动激活);FlaskGroup可嵌套进自定义 CLI; - 视图函数可直接返回生成器(generator);新增
stream_template/stream_template_string; - 调试/测试中的上下文保持机制重写:交互调试器中的
request、g指向正确数据,teardown 函数始终在请求结束时执行; View.init_every_request类属性:设为False后视图不再每请求新建实例。
2.1.x:CLI 与类型细节
2.1.0(2022-03-28)放弃 Python 3.6,Click 升到 >= 8.0;config.from_json 被 config.from_file(name, load=json.load) 取代;同一蓝图不允许以相同名称重复注册(注册时用 name= 指定唯一名);send_file 旧参数名的废弃期延长到 2.2。2.1.3 修复了命名空间包的 instance_path、flask run 新增 --exclude-patterns 选项,并改进了 render_template 在应用上下文外使用时的错误提示。
2.0.x(2021):告别 Python 2
2.0.0(2021-05-11)是“去 Python 2”的里程碑:
- 放弃 Python 2 与 Python 3.5;
- JSON 支持不再使用 simplejson,改用覆盖
app.json_encoder/json_decoder; - 新增
Config.from_file,可用toml.load等任意文件加载器加载配置; send_file变为werkzeug.utils实现的包装,参数改名(attachment_filename→download_name、cache_timeout→max_age、add_etags→etag)并默认conditional=True、max_age=None(即Cache-Control: no-cache,让浏览器走条件请求验证而非定时缓存);Scaffold类 成为Flask与Blueprint的共同 API 基础(当前仓库中为 src/flask/sansio/scaffold.py);- 新增按 HTTP 方法的快捷路由装饰器,如
@app.post("/login"); - 支持异步视图、异步错误处理器、异步 before/after request 与 teardown 函数;
- 支持嵌套蓝图;
- 视图返回
(response, headers)元组时,headers 是“替换”而非“扩展”原有响应头; .env/.flaskenv加载默认 UTF-8 编码;flask shell在有readline时启用 tab 补全与历史记录。
2.0.1 补充了嵌套蓝点的点分注册名、register_blueprint(name=...) 选项,并恢复了 send_from_directory 的 filename 参数(改名 path,旧名废弃)。2.0.2 修正了 before_request 等回调的调用顺序(从 app 到最近的嵌套蓝图)。
1.x 系列:现代 Flask 的地基
1.1.0(2019-07-04)
- 视图函数可以直接返回 dict,自动经
jsonify转为application/json响应——这是如今 API 写法的重要来源; send_file支持PathLike对象(pathlib.Path)与BytesIO部分内容(partial content);- 500 错误处理器现在总是收到
InternalServerError实例,原始异常挂在e.original_exception上,行为更一致; Flask.logger名称改为与Flask.name一致,支持同进程多应用;- 蓝图拥有自己的
cliClick 组,可注册 CLI 命令; flask run新增--extra-files选项让 reloader 监视额外文件;- URL 匹配时机移到请求上下文 push 之后,自定义 URL 转换器可以访问 app 与请求上下文;
flask.testing.make_test_environ_builder废弃,由flask.testing.EnvironBuilder取代。
1.0(2018-04-26)
1.0 是稳定性里程碑,代表性变更:
- 放弃 Python 2.6 与 3.3;依赖提升到 Werkzeug >= 0.14 等;
jsonify默认紧凑输出(JSONIFY_PRETTYPRINT_REGULAR默认改为False),debug 模式下缩进;Flask.add_url_rule接受provide_automatic_options参数,可关闭自动 OPTIONS;- 新增
routesCLI 命令输出应用已注册的路由; FLASK_APP可以指向应用工厂,且可以带参数,例如FLASK_APP=myproject.app:create_app('dev');零参数工厂create_app/make_app可被自动检测;- 当安装了 python-dotenv 时,
flask命令与Flask.run自动从.env与.flaskenv加载环境变量; - session 一旦在请求中被访问,响应头加上
Cookie到Vary; SESSION_COOKIE_SAMESITE控制 SameSite 属性;- 子域匹配默认关闭,
SERVER_NAME不再隐式开启它; - 移除
flask.ext命名空间(扩展改为直接import flask_sqlalchemy这类名字)等旧 API; - 开发服务器默认使用线程;
APPLICATION_ROOT默认为/;debug 模式下默认启用TRAP_BAD_REQUEST_ERRORS。
0.x 系列:从预览版到微框架(2010—2016)
0.x 系列奠定了 Flask 的形态,早期版本带有酒名代号(codename):
- 0.1(2010-04-16):首个公开预览版。
- 0.2:集成 JSON 支持、
send_file、模块化(Module)支持、Google App Engine 支持、永久性 session 选项。 - 0.3(Schnaps):闪消息分类(categories)、应用配置
logging.Handler、上下文绑定支持控制台交互、配置系统雏形。 - 0.4:
after_request在异常进入错误处理页时也会执行、TESTING开关、make_response前身。 - 0.5(Calvados):
SERVER_NAME修复子域问题;自动转义收窄到.html/.htm/.xml/.xhtml;send_file输出 etag 并支持条件响应;MAX_CONTENT_LENGTH的前身概念出现于 0.6。 - 0.6(Whisky):自动实现 OPTIONS;
after_request反序调用;MAX_CONTENT_LENGTH配置限制请求体大小;make_response函数;基于 blinker 的信号支持(当时可选);模块可绑定子域。 - 0.7(Grappa):
teardown_request装饰器(无论是否异常都执行);after_request在异常时不再执行;用户异常处理器;safe_join;类视图;PROPAGATE_EXCEPTIONS配置。 - 0.8(Rakija):会话接口(session interface) 重构,可不覆写 Flask 类更换 session 实现;
before_first_request;TestClient.session_transaction;应用实例路径(instance path)概念——运行期可写文件的专属目录;APPLICATION_ROOT配置。 - 0.9(Campari,2012-07-01):
Flask.app_context出现(URL 生成不再强依赖请求上下文);url_for支持锚点与按 HTTP 方法生成;视图可返回(response,)元组;Flask.run的 host/port 接受None;render_template接受模板名迭代器;after_this_request与stream_with_context。 - 0.10(Limoncello):session cookie 序列化从 pickle 换成 JSON(降低密钥泄露影响面);
template_test/template_global;g移到应用上下文并支持get()与in判断;request.get_json()取代request.json;JSON 键排序默认开启以避免不同 worker 间哈希种子差异打乱 HTTP 缓存。 - 0.11(Absinthe):
jsonify支持顶层数组;before_render_template信号;SESSION_REFRESH_EACH_REQUEST配置;返回(response, headers)元组;Config.from_json/from_mapping;TEMPLATES_AUTO_RELOAD;flaskCLI 与flask.cli模块出现并取代 Flask-Script;特定类错误处理器优先匹配。 - 0.12(Punsch):
send_file支持 range 请求、移除不可靠的 mimetypes 猜测;应用日志默认关闭传播;开发服务器崩溃行为回退为返回 500。
从 0.12.5(2020-02-10,Pin Werkzeug < 1.0.0)到 1.1.4(2021-05-13)之间,各补丁版本主要处理安全与兼容问题,例如 0.6.1 修复了 Windows 下反斜杠路径穿越的任意文件下载漏洞、1.0.4 修复了 BadRequestKeyError 在非 debug 模式丢失关键信息的问题。
Python 版本支持与依赖最低版本演进
将 CHANGES.rst 中的条目串起来,可以还原出 Flask 对运行环境的完整要求演进(“从源码结构看”,当前仓库的实际约束与变更日志一致):
| 版本 | Python 支持 | 关键依赖最低版本 |
|---|---|---|
| 0.1–1.0 | 2.6/2.7、3.3+ | Werkzeug >= 0.14、Jinja >= 2.10(1.0) |
| 1.1–2.1 | 3.5+(2.1 起 3.6+) | Werkzeug >= 0.15、Click >= 8.0(2.1) |
| 2.2–2.3 | 3.7+(2.3 起) | Werkzeug >= 2.3、Jinja2 >= 3.1.2(2.3.0) |
| 3.0 | 3.8+ | Werkzeug >= 3.0.0 |
| 3.1 | 3.9+ | Werkzeug >= 3.1、ItsDangerous >= 2.2、Blinker >= 1.9 |
| 3.2(dev) | 3.10+ | 同上,见 pyproject.toml |
当前仓库 pyproject.toml 声明 requires-python = ">=3.10",依赖为 blinker>=1.9.0、click>=8.1.3、itsdangerous>=2.2.0、jinja2>=3.1.2、markupsafe>=2.1.1、werkzeug>=3.1.0;可选依赖为 asgiref>=3.2(async)与 python-dotenv(dotenv)。仓库的 tox 配置同时维护 tests-min 环境,用上述最低版本组合跑测试,保证“最低版本可用”的承诺。
如何基于变更日志做版本升级
结合 CHANGES.rst 的编排方式,升级实践可以归纳为四步:
- 核对 Python 与依赖版本:先对照上表确认解释器与依赖满足目标版本,例如升级到 3.2 需要 Python >= 3.10。
- 按“移除”条目逐条排查:每个大版本的 “Remove previously deprecated code” 子列表(如 2.3.0、3.0.0、3.2.0)就是必须迁移的 API 清单。例如还在用
app.env、before_first_request、json_encoder、FLASK_ENV的项目,需要先清理到 2.3 兼容状态,再进入 3.x。 - 用警告验证而非猜测:Flask 的废弃期设计是“检测到旧用法就给出 DeprecationWarning”(例如 src/flask/app.py 对
should_ignore_error覆写的检测),因此建议在开发环境以“警告视为错误”的方式跑完整测试套件。仓库自身的测试配置也印证这一策略——pyproject.toml 中 pytest 的filterwarnings = ["error"]。 - 优先带上安全修复版本:带
:ghsa:标记的条目(3.1.1 密钥轮换顺序、3.1.3 session 访问标记、2.3.2 Werkzeug 依赖安全更新)应作为跳版本升级的直接依据。
另外两个迁移提示:获取版本号请改用 importlib.metadata.version("flask")(__version__ 已废弃并将在 3.2.0 移除);涉及 redirect 默认状态码变化的代码,若有依赖 302 的测试断言,升级 3.2 时需显式传 code=302 或更新断言为 303(参见 src/flask/helpers.py 的现行签名)。
小结
CHANGES.rst 记录的不只是版本号的推进,而是 Flask 从 2010 年的单文件预览版成长为现代 WSGI 微框架的完整技术决策轨迹:0.x 建立路由、蓝图、上下文与会话体系,1.0 锁定稳定 API 并引入工厂模式与 CLI,2.0 告别 Python 2、引入异步与嵌套蓝图,2.2/2.3 用 contextvars 与 JSON 提供者完成内部现代化并大规模清除废弃 API,3.x 则聚焦安全加固(密钥轮换、可信主机、资源限制)与 3.2.0 中 RequestContext/AppContext 合并这类深水区重构。对维护既有项目的开发者而言,这份日志加上 src/flask/ 下的源码验证,是评估升级成本最可靠的依据。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00