跳到正文
原文
Simon Willison·· 1 天前AI 评分55

Python 3.15 发布,开源项目可告别 3.10 并开始使用 3.11

Hello Python 3.15, goodbye 3.10, and now I can use 3.11

AI 导读

Python 3.15 已发布,Simon Willison 因此可让自己的开源项目停止支持已结束官方支持的 Python 3.10,并开始使用 3.11 的特性。

正文 · AI 翻译

12th October 2026

Python 3.15 来了!这是今年由 3.14 和 3.15 发布经理 Hugo van Kemenade 编选的必备 Python 3.15 新特性指南。作为一名构建能在每个受支持的 Python 版本上运行的开源软件的人,我得以告别 Python 3.10,并开始拥抱 Python 3.11 的特性。

首先,来看 Python 3.15 的一些亮点。

显式惰性导入

我最兴奋的是来自 PEP 810 的 显式惰性导入。它们让你可以这样导入模块:

lazy import json
lazy from pathlib import Path

随后,这些符号在后面的代码中第一次被使用时,该模块才会被导入。

我的 LLM CLI 工具实现了插件。我不得不在插件作者文档中 建议手动惰性导入,因为仅仅安装使用了 sentence_transformers 这类重型依赖的插件,就可能让每次调用 llm 命令都增加数秒。惰性导入直接解决了这一启动开销。

推导式中的解包

新的 [*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,并于 2015 年落地 于 Python 3.5。

采样分析器

Python 现有的跟踪分析器已从 cProfile 更名为 profiling.tracing,并新增了一个令人兴奋的采样分析器 Tachyon,即 profiling.sampling。

采样分析器的工作方式是定期从正在运行的进程中捕获栈跟踪,然后据此计算哪些函数内部花费的时间最多。它们开销极低,无需事先对系统进行插桩,就能深入洞察正在运行的系统。

我 以前用过的工具 包括 py-spy 之类。现在这项能力已内置到标准库中。

如果你有一个现有 Python 3.15 进程的 PID,可以运行以下命令开始采集样本(在 macOS 上我不得不使用 sudo):

sudo uv run --python 3.15 python -m profiling.sampling attach 1234

与主程序交互一会儿,然后按 Ctrl+C 停止采集并查看报告,大致如下:

Screenshot of terminal output from a Python sampling profiler with colored text on a black background. Header lines report 2,651 samples captured in 2.65 seconds at a sample rate of 999.98 samples/sec with an error rate of 0.19. A Profile Stats table with columns for nsamples, sample%, tottime, cumul%, cumtime and filename:lineno(function) shows that 99.9% of samples (2.644 seconds) were spent directly in selectors.py KqueueSelector.select, meaning the process was almost entirely idle waiting on the asyncio event loop. The rest of the table lists the call stack beneath it with zero direct time but 100% cumulative presence: asyncio base_events.py run_once, run_forever and run_until_complete, runners.py Runner.run and run, cli.py serve and sqlite_extensions wrapped, and several click core.py invoke, main and call frames. A legend explains each column, followed by a Summary of Interesting Functions section listing hot spots (KqueueSelector.select at 99.9% direct samples), the most frequently present functions on the stack (run_forever, run_until_complete and Runner.run at 100%), and the highest call magnification (2645.0x for BaseEventLoop._run_once).

它还可以生成 这样的火焰图 和 这样的热力图,甚至可以输出能在 Firefox 分析器界面中查看的格式。

3.15 并没有比 3.14 快多少

Miguel Grinberg 前几天针对 3.15.0rc3 版本调查了 Python 3.15 有多快?,发现性能大体与 3.14 相同,实验性 JIT 除外。JIT 相比标准 3.15 解释器带来了 1.2 倍提升(在斐波那契测试中),这是 Miguel 首次观察到有意义的 JIT 性能提升。

Miguel 去年 对 3.14 的探索 发现,相较于 Python 3.13,在更多类别上都有显著提升。

使用 uv 升级到 Python 3.15

我使用以下一系列命令,让 uv 在我的 Mac 上使用 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

Python 3.11 的亮点

3.15 的发布意味着 Python 3.10(2021 年发布)已正式不再受支持。

我对主要开源项目的策略是让它们在每个受支持的 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 类型系统的改进。

我计划在接下来几周把 Python 3.11 的改进落地到我的一批项目中。这是我的第一个 Datasette PR,用于移除那个 set_authorizer(None) 变通方案。

我还更新了 click-app、datasette-plugin、python-lib 和 llm-plugin cookiecutter 模板,以针对 Python 3.11 到 Python 3.15 进行测试。

来源:Simon Willison · simonwillison.net