文章介绍 Python 3.15 的显式惰性导入与推导式解包,并讨论停止兼容 3.10 后使用 3.11 特性的机会。惰性导入可将重型插件依赖的加载推迟到首次使用,缓解命令行工具启动延迟。
Python 3.15 来了!想了解关键变化,可以看看《Python 3.15 新特性》指南,今年由 Python 3.14 和 3.15 的发布经理 Hugo van Kemenade 主编。我的开源软件需要兼容所有仍受支持的 Python 版本,所以现在终于可以告别 Python 3.10,开始用上 Python 3.11 的特性了。
先来看看 Python 3.15 的几个亮点。
最让我兴奋的是 PEP 810 中的显式 lazy import。现在可以这样导入模块:
lazy import json
lazy from pathlib import Path
只有当后续代码第一次使用这些符号时,对应的模块才会真正导入。
我的 LLM CLI 工具支持插件。我之前不得不在插件作者文档里建议大家手动实现 lazy import,因为只要安装了使用 sentence_transformers 这类重量级依赖的插件,每次调用 llm 命令就可能多花几秒钟。lazy import 直接解决了这部分启动开销。
新的 [*sublist for sublist in lists] 解包语法也很不错。下面是文档中的示例:
lists = [[1, 2], [3, 4], [5]]
[*L for L in lists]
# [1, 2, 3, 4, 5]
# equivalent to [x for L in lists for x in L]
sets = [{1, 2}, {2, 3}, {3, 4}]
{*s for s in sets}
# {1, 2, 3, 4}
# equivalent to {x for s in sets for x in s}
dicts = [{'a': 1}, {'b': 2}, {'a': 3}]
{**d for d in dicts}
# {'a': 3, 'b': 2}
# equivalent to {k: v for d in dicts for k,v in d.items()}
Adam Hartz 和 Erik Demaine 提出的 PEP 798《推导式中的解包》,是在 PEP 448 解包语法基础上的扩展。PEP 448 早在 2015 年就随 Python 3.5 发布了。
Python 原有的追踪式 profiler 从 cProfile 更名为 profiling.tracing,同时还新增了一个令人期待的采样式 profiler,名叫 Tachyon,也就是 profiling.sampling。
采样式 profiler 会定期抓取运行中进程的调用栈,再用这些数据计算哪些函数耗时最多。这类工具开销很低,无须事先给系统添加插桩代码,就能深入了解系统的运行情况。
我以前用过 py-spy 这样的工具。现在,这项能力已经内置到标准库里了。
只要知道一个正在运行的 Python 3.15 进程的 PID,就可以运行下面的命令开始采样(在 macOS 上,我必须使用 sudo):
sudo uv run --python 3.15 python -m profiling.sampling attach 1234
与主程序交互一会儿,然后按 Ctrl+C 停止采样,就能看到一份类似这样的报告:

它还可以生成火焰图和热力图,甚至能输出可在 Firefox profiler UI 中查看的格式。
前几天,Miguel Grinberg 用 3.15.0rc3 版本研究了“Python 3.15 有多快?”这个问题。他发现,除了实验性的 JIT,性能基本与 3.14 相同。在 Fibonacci 测试中,JIT 的性能是标准 3.15 解释器的 1.2 倍,这是 Miguel 第一次观察到 JIT 带来明显的性能提升。
去年,Miguel 测试 3.14 时发现,相比 Python 3.13,它在更多类别的测试中都有显著提升。
我在 Mac 上用下面这组命令,让 uv 使用 Python 3.15。首先得升级 uv 本身,确保它能识别这个新版本:
uv self update
然后安装 3.15 稳定版:
uv python install 3.15
接着告诉 uv:除非项目本身固定了其他版本,否则每次运行 uv run 命令时,都默认使用这个版本:
uv python pin --global 3.15
现在,下面的命令会显示版本为 3.15:
uv run python --version
我已经通过 uv tool install 安装了不少工具。可以像这样重新安装,让它们使用 Python 3.15:
uv tool upgrade datasette --python 3.15
然后用下面的命令确认版本:
datasette --get /-/versions.json | jq
3.15 的发布意味着,2021 年发布的 Python 3.10 正式结束支持。
我对主要开源项目的维护原则是:兼容所有仍受支持的 Python 版本。现在可以移除对 3.10 的支持,开始使用 3.11 引入的特性了。
可以看看《Python 3.11 新特性》文档。我终于可以放心依赖内置的 tomllib 了!
Datasette 大量使用 asyncio。3.11 新增了 TaskGroup、timeout(),以及其他几项新特性。
datetime.UTC 是 3.11 新增的 datetime.timezone.utc 别名。
Python 对 SQLite 的支持在 3.11 中也有几项重要升级,包括:
setlimit() 和 getlimit() 提供了从 Python 设置 SQLite 运行时限制的机制。
create_window_function() 让我们可以用 Python 创建自定义窗口函数,只需定义一个带有 step()、value()、inverse() 和 finalize() 方法的类。
blobopen() 提供了一种高效的机制,可以对 SQLite 行中存储的大型 BLOB 二进制值进行局部读写。
现在可以调用 set_authorizer(None) 移除 SQLite authorizer。Datasette 之前为此专门做了变通处理!
此外,Python 的 typing 系统也有一大批改进。
我计划在接下来的几周里,为多个项目引入 Python 3.11 的改进。这是我的第一个 Datasette PR,移除了针对 set_authorizer(None) 的变通处理。
我还更新了 click-app、datasette-plugin、python-lib 和 llm-plugin 这几个 cookiecutter 模板,让它们在 Python 3.11 到 Python 3.15 上运行测试。
用我的声音为博客构建一项新功能 —— 2026 年 10 月 9 日
Claude Haiku 5.5 —— 2026 年 10 月 7 日
我们几乎需要给所有东西默认设置严格的预算上限 —— 2026 年 10 月 3 日
OpenAI DevDay 2026 实时博客 —— 2026 年 9 月 29 日
本文是 Simon Willison 撰写的《你好 Python 3.15,再见 3.10,现在我终于能用 3.11 了》,发布于 2026 年 10 月 12 日。
上一篇:用我的声音为博客构建一项新功能
每月赞助我 10 美元,即可收到一封精选邮件摘要,了解当月最重要的 LLM 进展。
付费支持我,让我给你发得更少!