首页
/ Flask 版本演进全解:从 CHANGES.rst 读懂 Flask 从 0.1 到 3.2 的关键变更与升级要点

Flask 版本演进全解:从 CHANGES.rst 读懂 Flask 从 0.1 到 3.2 的关键变更与升级要点

2026-09-03 15:22:03作者:殷蕙予

本文以仓库中的 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.devpyproject.toml 第 3 行),即 3.2.0 条目尚未发布,其中的行为变更在正式发布前可能微调。

3.x 系列:现代化重构与安全加固(当前主线)

3.0.0(2023-09-30):Sans-IO 架构与旧代码清除

3.0.0 是架构层面的一次大版本,核心变更包括:

  • 移除此前所有已废弃的代码;
  • 将代码重构为 Sans-IO 基础类FlaskBlueprint 类获得了 Sans-IO 基类,IO 相关行为被拆分出来,这一结构在仓库中体现为 src/flask/sansio/ 目录,其中的 app.pyblueprints.pyscaffold.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_SIZEMAX_FORM_PARTS 配置;
  • 支持 Partitioned cookie 属性(CHIPS),对应 SESSION_COOKIE_PARTITIONED 配置;
  • 新增 SECRET_KEY_FALLBACKS 密钥轮换 配置:一个旧密钥列表,仍可用于验证(unsign)旧会话。

从源码可以验证密钥轮换的实现:src/flask/sessions.pySecureCookieSessionInterface.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=Truesubdomain_matching=FalseSERVER_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)

  • 对只访问键而不访问值的操作(如 inlen),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.tomlrequires-python = ">=3.10" 已生效);
  • 移除此前已废弃的 __version__
  • RequestContextAppContext 合并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_filtertemplate_testtemplate_global 装饰器可以不带括号使用;
  • redirect 默认状态码从 302 改为 303:303 指示客户端无论原请求是 GET 还是 POST 都切换为 GET,兼容 HTMX 等前端库。源码中两处签名均已确认:src/flask/helpers.pyredirect(location, code: int = 303, ...)src/flask/sansio/app.pyFlask.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_namesend_file_max_age_defaultuse_x_sendfilepropagate_exceptionstemplates_auto_reloadapp 上的属性移除,改为直接读配置键;
  • JSON_AS_ASCIIJSON_SORT_KEYSJSONIFY_MIMETYPEJSONIFY_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 引入的替代性变更:escapeMarkup 应直接从 markupsafe 导入(flask 中的导出被标记废弃);信号永远可用,blinker>=1.6.2 成为必需依赖,signals_available 属性废弃;信号支持 async 订阅函数;打包改用 pyproject.tomlsetup.cfg 移除);空名称的蓝图直接抛 ValueErrorSESSION_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.tomlbuild-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_forflask.abort 调用 app.aborter(可用 Flask.aborter_class / make_aborter 定制),flask.redirect 调用 app.redirectflask.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
  • 调试/测试中的上下文保持机制重写:交互调试器中的 requestg 指向正确数据,teardown 函数始终在请求结束时执行;
  • View.init_every_request 类属性:设为 False 后视图不再每请求新建实例。

2.1.x:CLI 与类型细节

2.1.0(2022-03-28)放弃 Python 3.6,Click 升到 >= 8.0;config.from_jsonconfig.from_file(name, load=json.load) 取代;同一蓝图不允许以相同名称重复注册(注册时用 name= 指定唯一名);send_file 旧参数名的废弃期延长到 2.2。2.1.3 修复了命名空间包的 instance_pathflask 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_filenamedownload_namecache_timeoutmax_ageadd_etagsetag)并默认 conditional=Truemax_age=None(即 Cache-Control: no-cache,让浏览器走条件请求验证而非定时缓存);
  • Scaffold 成为 FlaskBlueprint 的共同 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_directoryfilename 参数(改名 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 一致,支持同进程多应用;
  • 蓝图拥有自己的 cli Click 组,可注册 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;
  • 新增 routes CLI 命令输出应用已注册的路由;
  • FLASK_APP 可以指向应用工厂,且可以带参数,例如 FLASK_APP=myproject.app:create_app('dev');零参数工厂 create_app / make_app 可被自动检测;
  • 当安装了 python-dotenv 时,flask 命令与 Flask.run 自动从 .env.flaskenv 加载环境变量;
  • session 一旦在请求中被访问,响应头加上 CookieVary
  • 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.4after_request 在异常进入错误处理页时也会执行、TESTING 开关、make_response 前身。
  • 0.5(Calvados)SERVER_NAME 修复子域问题;自动转义收窄到 .html / .htm / .xml / .xhtmlsend_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_requestTestClient.session_transaction;应用实例路径(instance path)概念——运行期可写文件的专属目录;APPLICATION_ROOT 配置。
  • 0.9(Campari,2012-07-01)Flask.app_context 出现(URL 生成不再强依赖请求上下文);url_for 支持锚点与按 HTTP 方法生成;视图可返回 (response,) 元组;Flask.run 的 host/port 接受 Nonerender_template 接受模板名迭代器;after_this_requeststream_with_context
  • 0.10(Limoncello):session cookie 序列化从 pickle 换成 JSON(降低密钥泄露影响面);template_test / template_globalg 移到应用上下文并支持 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_mappingTEMPLATES_AUTO_RELOADflask CLI 与 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.0click>=8.1.3itsdangerous>=2.2.0jinja2>=3.1.2markupsafe>=2.1.1werkzeug>=3.1.0;可选依赖为 asgiref>=3.2(async)与 python-dotenv(dotenv)。仓库的 tox 配置同时维护 tests-min 环境,用上述最低版本组合跑测试,保证“最低版本可用”的承诺。

如何基于变更日志做版本升级

结合 CHANGES.rst 的编排方式,升级实践可以归纳为四步:

  1. 核对 Python 与依赖版本:先对照上表确认解释器与依赖满足目标版本,例如升级到 3.2 需要 Python >= 3.10。
  2. 按“移除”条目逐条排查:每个大版本的 “Remove previously deprecated code” 子列表(如 2.3.0、3.0.0、3.2.0)就是必须迁移的 API 清单。例如还在用 app.envbefore_first_requestjson_encoderFLASK_ENV 的项目,需要先清理到 2.3 兼容状态,再进入 3.x。
  3. 用警告验证而非猜测:Flask 的废弃期设计是“检测到旧用法就给出 DeprecationWarning”(例如 src/flask/app.pyshould_ignore_error 覆写的检测),因此建议在开发环境以“警告视为错误”的方式跑完整测试套件。仓库自身的测试配置也印证这一策略——pyproject.toml 中 pytest 的 filterwarnings = ["error"]
  4. 优先带上安全修复版本:带 :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/ 下的源码验证,是评估升级成本最可靠的依据。

登录后查看全文
热门项目推荐
相关项目推荐