Python 3.15 新功能完整指南:lazy import 加速啟動、內建 frozendict 與 sentinel、Tachyon 剖析器、UTF-8 預設編碼(2026)
直接答案:Python 3.15 將於 2026 年 10 月正式發布(目前已出 RC2)。重點新功能包括 lazy import 延遲導入、內建 frozendict/sentinel、Tachyon 取樣剖析器、UTF-8 預設編碼與推導式解包語法;升級前請先檢查 UTF-8 編碼相依與已移除的舊模組。
Python 3.15 的版本管理員 Hugo van Kemenade 在 9 月 1 日發布了 3.15.0 RC2(Release Candidate 2)——這是正式版前最後一個候選版,代表 API 已經凍結,接下來只會修 bug。對開發者來說,現在正是測試自家專案相容性的最佳時機(官方強烈鼓勵維護者在這段期間發布 3.15 的 wheel)。這篇指南幫你把本版最重要的變化一次整理清楚,附上可直接執行的程式碼範例。
Python 3.15 發布時程
| 階段 | 時間 | 說明 |
|---|---|---|
| 3.15.0 RC1 | 2026 年 8 月 | 第一個候選版 |
| 3.15.0 RC2 | 2026 年 9 月 1 日 | 最後候選版,API 凍結 |
| 3.15.0 正式版 | 2026 年 10 月 | 正式發布 |
| 3.16.0 alpha | 2026 年 10 月起 | 下一個開發週期開始 |
本版的 11 個核心 PEP 涵蓋效能(lazy import、JIT、frame pointers)、語言(frozendict、sentinel、推導式解包)、型別系統(TypedDict、TypeForm)與平台行為(UTF-8 預設)四大方向:
flowchart LR
A[Python 3.15] --> B[效能]
A --> C[語言新語法]
A --> D[型別系統]
A --> E[編碼與相容]
B --> B1[lazy import 延遲導入]
B --> B2[JIT 編譯器升級]
B --> B3[Tachyon 取樣剖析器]
B --> B4[Frame pointers 預設開啟]
C --> C1[內建 frozendict]
C --> C2[內建 sentinel]
C --> C3[推導式中解包]
D --> D1[TypedDict extra_items]
D --> D2[TypeForm]
E --> E1[UTF-8 預設編碼]
E --> E2[移除 sre_* / profile 棄用]PEP 810:lazy import 顯式延遲導入,啟動速度有感提升
大型應用啟動慢的元兇,常常是 import 一堆根本沒用到的模組。過去開發者只能把 import 搬進函式內、用 importlib 手動載入,或重整依賴結構——都很破壞可讀性。Python 3.15 給了一個乾淨的解法:lazy 軟關鍵字。
# 宣告延遲導入:此時模組尚未真正載入
lazy import json
lazy from pathlib import Path
print("應用程式啟動中...") # json 與 pathlib 都還沒載入
# 首次使用時才透明地真正載入
data = json.loads('{"python": "3.15"}') # 這裡才載入 json
p = Path(".") # 這裡才載入 pathlib
其他控制方式:
- 全域啟用:
python -X lazy_imports=all或環境變數PYTHON_LAZY_IMPORTS=all,讓所有 import 都變成延遲載入。 - 過濾器:用
sys.set_lazy_imports_filter()傳入函式,決定哪些模組延遲、哪些維持立即載入:
import sys
def myapp_filter(importing, imported, fromlist):
# 只延遲應用程式內部的子模組
return imported.startswith("myapp.")
sys.set_lazy_imports_filter(myapp_filter)
sys.set_lazy_imports("all")
- 舊版相容:可在模組中宣告
__lazy_modules__ = ["json", "pathlib"],3.15 會自動把這些模組視為延遲導入,舊版 Python 則視為一般 import。
⚠️ 限制:lazy 只能在模組層級使用(函式、類別、try/except 內會 SyntaxError);不支援星號導入與 __future__ 導入。延遲模組若不存在,錯誤會等到首次使用時才拋出。
PEP 814 + PEP 661:內建 frozendict 與 sentinel
frozendict:不可變字典終於內建
以前想要「唯讀字典」只能靠第三方套件或 MappingProxyType。3.15 直接內建 frozendict:
config = frozendict(host="localhost", port=8000)
print(config["host"]) # localhost
try:
config["port"] = 9000
except TypeError as e:
print(e) # 'frozendict' object does not support item assignment
# 支援 | 合併運算子(回傳新的 frozendict)
new_config = config | frozendict(debug=True)
只要鍵與值都可雜湊,frozendict 本身就能當 dict 的鍵、放進 set,或當 @functools.lru_cache() 的參數;copy、json、pickle、pprint 等標準庫已全面支援。適合拿來當不可變設定檔、快取鍵或 API 回傳值,從根本上防止意外修改。
sentinel:告別 object() 哨兵
過去寫「參數沒傳」的哨兵值,只能 MISSING = object(),字串表達難看、不能 pickle。3.15 內建 sentinel 型別解決這些問題:
MISSING = sentinel("MISSING")
def get_config(key, default=MISSING):
if default is MISSING:
print("使用者未提供預設值")
else:
print(f"使用者提供了預設值: {default}")
get_config("timeout", default=None) # None 是合法值,不會被誤判為「缺失」
sentinel 有清楚的 repr(如 <sentinel 'MISSING'>)、支援 pickle(只要在模組中可依名稱導入)、對型別檢查工具友善(可直接用 | 做型別聯集)。最經典的使用場景,就是區分「呼叫者沒傳參數」與「呼叫者傳了 None」。
PEP 799:全新 profiling 套件與 Tachyon 取樣剖析器
3.15 把效能剖析工具重整到新的 profiling 命名空間:
profiling.tracing:原本的cProfile(保留為相容別名)。profiling.sampling:全新 Tachyon 統計取樣剖析器。- 純 Python 的舊
profile模組宣告棄用(3.17 移除)。
Tachyon 最大的賣點:對受測程式近乎零開銷,而且可以附加到線上程序。它從外部進程透過作業系統 API(Linux 的 ptrace、macOS 的 task_for_pid)直接讀取目標記憶體,每秒對呼叫棧取樣(預設 1000Hz,最高 1,000,000Hz),不需要執行任何額外的 Python 位元組碼:
# 剖析一個腳本
python -m profiling.sampling run my_script.py
# 附加到正在跑的生產程序(免重啟,需 sudo)
python -m profiling.sampling attach --pid 12345 --flamegraph
# 對卡住的程序做單次堆疊快照
python -m profiling.sampling dump --pid 12345
剖析模式有 wall(預設,含 I/O 等待)、cpu(純 CPU 時間)、gil(持有 GIL 時間,抓多執行緒瓶頸)、exception(只取樣正在處理異常的執行緒)。進階功能包括非同步感知(--async-aware,從協程邊界重建邏輯堆疊)、指令級剖析(--opcodes)、以及內建火焰圖(--flamegraph)、行級熱圖(--heatmap)與 Firefox profiler 格式(--gecko)輸出。線上 debug 效能問題不用再重啟服務,這對維運人員是福音。
PEP 686:UTF-8 成為預設編碼(Windows 使用者影響最大)
從 3.15 開始,UTF-8 模式預設啟用:open('file.txt') 這類沒指定 encoding 的檔案讀寫,一律用 UTF-8,不再跟隨作業系統語系(Windows 過去會用 ANSI 代碼頁)。
# 3.15 之後這行一律以 UTF-8 讀取
with open("data.txt") as f:
content = f.read()
- 好處:讀寫 JSON、TOML 等標準格式不再踩編碼地雷;多數 Unix 系統本來就預設 UTF-8,所以受影響最大的是 Windows 使用者。
- 風險:舊程式若隱式依賴平台預設編碼讀寫非 UTF-8 檔案,升級後可能出現
UnicodeError、亂碼,甚至資料損壞。 - 應對:想還原舊行為可設
PYTHONUTF8=0或-X utf8=0;開啟EncodingWarning找出漏寫 encoding 的程式碼;確定要跟系統語系走就明確寫encoding="locale"。
升級前的黃金守則:先把所有 open() 補上明確的 encoding= 參數,一勞永逸。
PEP 798:推導式中解包(unpacking in comprehensions)
列表、集合、字典推導式與生成器表達式,現在最外層支援 * 與 ** 解包,取代繁瑣的巢狀推導式或 itertools.chain():
# 列表扁平化
nested = [[1, 2], [3, 4], [5]]
flat = [*L for L in nested] # [1, 2, 3, 4, 5]
# 多個集合取聯集
sets = [{1, 2}, {2, 3}, {3, 4}]
merged = {*s for s in sets} # {1, 2, 3, 4}
# 多個字典合併(重複鍵後者覆蓋)
dicts = [{"a": 1}, {"b": 2}, {"a": 3}]
merged_dict = {**d for d in dicts} # {'a': 3, 'b': 2}
# 生成器表達式
gen = (*L for L in nested)
注意限制:列表/生成器表達式中不能用 **(如 [**x for x in y] 是 SyntaxError),字典的鍵/值位置也不能亂放解包。
型別系統強化:TypedDict 封閉與 TypeForm
PEP 728:TypedDict 支援 closed=True 與 extra_items——過去 TypedDict 預設「開放」(多餘鍵不管),現在可以限制:
from typing import TypedDict, ReadOnly
class MovieWithExtras(TypedDict, extra_items=ReadOnly[int | str]):
name: str
year: int
m1 = MovieWithExtras(name="Inception", year=2010, director="Nolan") # OK
m2 = MovieWithExtras(name="Inception", year=2010, budget=160.0) # 型別錯誤:budget 要是 int/str
PEP 747:TypeForm——以前很難註明「這個參數是型別本身」,現在有了乾淨的標記:
from typing import Any, TypeForm
def cast[T](typ: TypeForm[T], value: Any) -> T:
...
效能底盤:JIT 升級 + Windows 尾調用解釋器
- JIT 編譯器大幅升級:3.13 引入的 Copy-and-Patch JIT 在 3.15 重寫了追蹤前端,現在能加速物件建立、運算子重載與生成器;x86-64 Linux 上幾何平均提升約 8–9%,AArch64 macOS 上更達 12–13%。
- PEP 831:Frame pointers 預設開啟:支援平台上預設啟用幀指標(代價約 0.5–2.3% 開銷),讓 profiler/debugger 能追蹤 JIT 產生的機器碼幀——跟 Tachyon 是絕配。
- Windows 64 位元尾調用解釋器:官方 Windows 版改用 MSVC 18 編譯並預設啟用尾調用(tail-calling)解釋器,pyperformance 測試比舊版 switch-case 解釋器快 15–20%,部分小型腳本啟動與執行可加速到 40%。
升級前必看:移除項目與不相容變更
| 類別 | 項目 | 影響 |
|---|---|---|
| 移除 | collections.abc.ByteString、typing.ByteString | 改用 isinstance(obj, collections.abc.Buffer) |
| 移除 | sre_compile / sre_constants / sre_parse | 私有模組,正常不會用到 |
| 移除 | CGIHTTPRequestHandler 與 python -m http.server --cgi | 沒有替代,直接換方案 |
| 移除 | pathlib.PurePath.is_reserved() | 改用 os.path.isreserved() |
| 棄用 | import profile | 改用 profiling.tracing,3.17 移除 |
| 棄用 | -b / -bb(BytesWarning) | 3.17 變成無效參數 |
| 棄用 | .pth 檔案用 import 行執行程式碼 | 改用 PEP 829 的 .start 啟動設定檔 |
| 行為變更 | sqlite3.connect() 除 database 外全變 keyword-only | 呼叫端要調整 |
| 行為變更 | argparse:add_argument('-f', '-foo') 的 dest 推導從 'f' 變 'foo' | 有踩到的要加顯式 dest |
另外,空 TypedDict 建構(TypedDict("TD"))與非公開關鍵字的 NamedTuple 建構也不再支援;ast.AST 直接實例化棄用(3.20 報錯)。PEP 829 也順帶引入了套件啟動設定檔(.start 檔),讓 site 模組能批次處理啟動設定——這是 .pth 進化的方向。
現在就測試:在 CI 矩陣加入 3.15
官方強烈鼓勵專案在 RC 階段就驗證相容性,RC 版 build 的 wheel 與正式版相容。GitHub Actions 可以這樣設定:
strategy:
matrix:
python-version: ["3.14", "3.15"]
steps:
- uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
check-latest: true
allow-prereleases + check-latest 會自動跟著最新 RC 走,正式版發布後自動切換到穩定版。
總結:3.15 值得升級嗎?
| 面向 | 3.15 給你的 |
|---|---|
| 啟動速度 | lazy import(PEP 810)+ 全域 -X lazy_imports=all |
| 運行效能 | JIT 8–13%、Windows 尾調用 +15–20% |
| 線上除錯 | Tachyon 附加式剖析、frame pointers 預設開啟 |
| 程式碼品質 | frozendict 防誤改、sentinel 區分 None、TypedDict 封閉 |
| 平台一致性 | UTF-8 預設(Windows 影響最大) |
結論:如果你的專案重度依賴啟動速度或跑在 Windows 上,3.15 的升級誘因很強;但升級前務必先跑一遍 EncodingWarning 檢查、掃描 sqlite3 呼叫與 argparse 的短選項 dest,把相容性雷區一次拆完。 等到 10 月正式版發布再上 production,現在用 RC 驗證正是時候。
延伸閱讀
- uv 完整教學 2026:Rust 寫的極速 Python 套件管理器,一個指令取代 pip、poetry、pyenv、pipx
- Python 進階資料結構:collections 模組完全攻略(第 11 章)
- Python 除錯指南:Logging 設定與 PDB 實戰(第 34 章)
- smolvm 完整教學:用硬體隔離 VM 安全執行不受信任的 Python 程式碼(AI Agent 沙箱實戰)
參考來源:Python 3.15.0 RC2 公告(discuss.python.org)、What’s New in Python 3.15 官方文件、Simon Willison 部落格、Python 3.15.0 RC1 下載頁
