Python 3.15 の新機能 - lazy imports と UTF-8 デフォルト化で何が変わるか

Python 3.15 の新機能 - lazy imports と UTF-8 デフォルト化で何が変わるか

作成日:
読了:約26分
更新日:
この記事を読む人におすすめPR / Amazonアソシエイト

当サイトは Amazon.co.jp を宣伝しリンクすることで紹介料を得る手段を提供する、Amazonアソシエイト・プログラムの参加者です。価格・在庫はリンク先の最新情報をご確認ください。

Python の年次リリースが、また一つ大きな節目を迎えます。Python 3.15 には、長年議論されてきた明示的な lazy imports(PEP 810)と、UTF-8 のデフォルト化(PEP 686)という、実務への影響が大きい2つの変更が入ります。

この記事は 2026年9月22日時点の情報です。Python 3.15.0 はまだ正式リリースされていません。PEP 790 のスケジュールでは、最終版のリリース予定日は 2026年10月1日。現在は 2026年9月1日に公開された 3.15.0rc2(最後のリリース候補の予定)の段階です。以下は公式ドキュメント(3.15.0rc2 時点)と各 PEP を一次ソースに整理したもので、最終版で細部が変わる可能性がある点はご了承ください。

Python 3.15 の注目点(早見表)

項目内容
PEP 810明示的な lazy imports。lazy import json で初回利用まで読み込みを遅延
PEP 686UTF-8 がデフォルトエンコーディングに。ロケールに依存しなくなる
PEP 814組み込み型 frozendict(イミュータブル・ハッシュ可能なマッピング)
PEP 661組み込みの sentinel()。object() によるセンチネル自作から卒業
PEP 798内包表記でのアンパック([*L for L in lists])
PEP 799profiling パッケージ新設。サンプリングプロファイラ Tachyon を同梱
PEP 803free-threaded ビルド向け Stable ABI(abi3t)
PEP 831フレームポインタをデフォルトで有効化(観測性の向上)
リリース2026年10月1日予定(現在 3.15.0rc2)。サポートは 2031年10月まで

リリース状況とサポート期限

まず現在地の確認です。手元の環境で確認すると、安定版はまだ 3.14 系です。

$ python3 --version
Python 3.14.7

Python Developer's Guide のバージョン一覧によると、各バージョンの位置づけは次のとおりです。

バージョンステータス初回リリースサポート終了
3.16開発中(main ブランチ)2027年10月6日予定-
3.15プレリリース2026年10月1日予定2031年10月
3.14バグフィックス2025年10月7日2030年10月
3.13バグフィックス2024年10月7日2029年10月

3.15.0rc2 のアナウンスでは、rc1 以降に76人のコントリビュータから約144件のバグ修正等が入ったこと、ここから先は ABI の変更がないため、サードパーティのライブラリ作者は 3.15 向け wheel の準備・公開を進めてほしい、という趣旨が述べられています。

NOTE

リリース候補の段階では「明確なバグ修正のみ」が取り込まれます。したがって本記事で扱う機能セット自体は、最終版でもほぼこのままになる見込みです。ただし細かな挙動やドキュメントの記述は変わり得るので、本番導入の判断は正式リリース後の What's New で再確認してください。

PEP 810: 明示的な lazy imports

3.15 の目玉が lazy imports です。lazy というソフトキーワードを import 文の前に置くと、その名前が初めて使われるまでモジュールのロードと実行が遅延されます。

lazy import の基本
lazy import json
lazy from pathlib import Path
 
print("Starting up...")  # この時点では json も pathlib もロードされていない
 
data = json.loads('{"key": "value"}')  # ここで json が実際にロードされる
p = Path(".")                          # ここで pathlib が実際にロードされる

期待される出力は次のようになります。起動時のログが先に出て、重いモジュールのロードは後回しになる、というのが体感できるポイントです。

出力
Starting up...

何が嬉しいのか

狙いは起動時間・メモリ使用量の削減です。特に CLI ツールでは「サブコマンドごとに必要なライブラリが違うのに、起動時に全部 import している」という構造が非常によくあります。PEP 810 では、実運用での導入事例としてCLI ツールで起動時間が50〜70%削減したという報告が挙げられています。

NOTE

数値は PEP 810 に記載された報告値であり、あらゆるアプリで再現するものではありません。効果は「起動時に何をどれだけ import しているか」に完全に依存します。自分のプロジェクトで測る場合は python -X importtime が手軽です。

書ける場所・書けない場所

lazy はどこにでも書けるわけではありません。公式ドキュメントに明記された制約は以下です。

  • モジュールスコープ限定。関数の中、クラス本体、try / except / finally ブロックの中で使うと SyntaxError
  • スター import は不可。lazy from module import * は SyntaxError
  • future import は不可。lazy from __future__ import ... も SyntaxError
これらは SyntaxError になります
def main():
    lazy import json  # SyntaxError: 関数スコープでは使えません
 
try:
    lazy import numpy  # SyntaxError: try ブロック内では使えません
except ImportError:
    numpy = None

ソースを書き換えずに有効化する

既存コードに手を入れずに遅延ロードを試したいケース向けに、3つの入口が用意されています。

手段指定方法
コマンドラインオプション-X lazy_imports=all
環境変数PYTHON_LAZY_IMPORTS=all
実行時 APIsys.set_lazy_imports() / sys.get_lazy_imports()

-X lazy_imports と PYTHON_LAZY_IMPORTS が取る値は2つです。all はすべての import をデフォルトで lazy にする、normal(既定値)はソース中の lazy キーワードだけを尊重する、という違いです。

さらに、モジュール単位で細かく制御したい場合は sys.set_lazy_imports_filter() にコールバックを渡せます。フィルタは「import 元のモジュール名(または None)」「import されるモジュール名」「fromlist(通常の import では None)」の3引数を受け取り、True を返せば遅延、False を返せば即時ロードになります。

古い Python と両立させる __lazy_modules__

lazy キーワードは 3.15 で追加された構文なので、それより前のバージョンでは構文エラーになります。3.14 以前もサポートしつつ 3.15 では遅延させたい、というライブラリ向けに、モジュール変数 __lazy_modules__ が用意されています。

__lazy_modules__ による後方互換な指定
__lazy_modules__ = ["json", "pathlib"]
 
import json     # lazy として扱われる
import os       # こちらは従来どおり即時ロード

完全修飾のモジュール名を並べておくと、通常の import 文が lazy キーワードと同じセマンティクスで扱われます。この書き方なら 3.15 未満の Python でも単なる文字列リストとして無視されるだけなので、構文エラーになりません。

注意点: 失敗のタイミングがずれる

遅延ロードの最大の落とし穴は、ImportError が import 文の行ではなく「名前を初めて使った行」で発生することです。起動直後に落ちてくれていたものが、リクエスト処理の途中やバッチの終盤で落ちるようになり得ます。

PEP 810 では例外チェーンを使った報告の強化(どこで lazy import が宣言され、どこで失敗したかを両方示す)が言及されていますが、失敗が後ろにずれるという性質そのものは変わりません。サーバアプリで -X lazy_imports=all を無条件に有効化するのは避け、まずは CLI や起動の速さが効く場所から、明示的な lazy キーワードで局所的に導入するのが安全です。

WARNING

副作用を持つモジュール(import 時にプラグイン登録やモニタリングの初期化を行うもの)を lazy にすると、その副作用が「いつ起きるか分からない」状態になります。import 時の副作用に依存している箇所は lazy 化の対象から外してください。

PEP 686: UTF-8 がデフォルトエンコーディングに

もう一つの大きな変更が、UTF-8 のデフォルト化です。公式ドキュメントは次のように説明しています。Python はシステム環境から独立して UTF-8 を既定のエンコーディングとして使うようになり、open('flying-circus.txt') のように encoding を省略した I/O は UTF-8 になります。

これまで open() の既定エンコーディングはロケール依存で、日本語の Windows 環境では CP932(Shift_JIS 系)になっていました。「Mac では動くのに Windows で UnicodeDecodeError」という古典的なトラブルの主因がこれです。3.15 ではその前提が変わります。

3.15 では encoding 省略でも UTF-8
# 3.14 以前: ロケール依存(日本語 Windows では CP932 など)
# 3.15 以降: 常に UTF-8
with open("memo.txt") as f:
    text = f.read()

影響と回避策

公式ドキュメントが挙げているポイントを整理します。

  • 適用されるのは encoding 引数を渡していない場合だけです。バージョン間の互換性を最大化したいなら、常に明示的に encoding を渡すのが最善です
  • 影響を受ける箇所の洗い出しには、オプトインのエンコーディング警告(EncodingWarning)が使えます
  • ロケールのエンコーディングを使いたい場合は、Python 3.10 からサポートされている encoding='locale' を明示します
  • 従来の挙動に戻したい場合は、環境変数 PYTHONUTF8=0 かコマンドラインオプション -X utf8=0 で UTF-8 モードを無効化できます

また PEP 686 には、ロケールのエンコーディングを UTF-8 モードの影響を受けずに取得する locale.getencoding() の追加も含まれます。

移行の進め方

PEP 686 が推奨する手順は「UTF-8 モードを一時的に無効化する」「EncodingWarning でエンコーディングに依存している箇所を洗い出す」「UTF-8 モードを有効にしてテストする」の3ステップです。実際には、3.14 以前の段階でも次のように警告を出して事前に棚卸しできます。

エンコーディング依存箇所の洗い出し
$ python3 -X warn_default_encoding -W error::EncodingWarning your_script.py

encoding を省略した open() や locale.getpreferredencoding() の呼び出しがあれば、そこで例外として浮かび上がります。CI に組み込んでおくと、3.15 に上げる前に差分を潰せます。

WARNING

逆方向のリスクもあります。CP932 で書かれたレガシーな CSV やログを「ロケール任せ」で読んでいたコードは、3.15 では UTF-8 として解釈され UnicodeDecodeError になります。読み込み側に encoding='cp932' を明示するのが正攻法です。文字コードそのものの前提知識は文字コード入門 - UTF-8 と Unicode の仕組みにまとめてあります。

組み込み型が2つ増える: frozendict と sentinel

PEP 814: frozendict

イミュータブルでハッシュ可能なマッピングが組み込み型として追加されます。

frozendict
>>> a = frozendict(x=1, y=2)
>>> hash(a)
3527539
>>> {a: "config"}       # 辞書のキーにできる
{frozendict({'x': 1, 'y': 2}): 'config'}

ポイントは以下です。

  • collections.abc.Mapping プロトコルを実装し、挿入順を保持します
  • キーはハッシュ可能である必要があり、値がハッシュ可能なら frozendict 自体もハッシュ可能になります。ハッシュ値は要素の順序に依存しません
  • ハッシュ可能なので、辞書のキー・集合の要素・@functools.lru_cache() を付けた関数の引数に使えます
  • マージ演算子 | と |= を dict との間でサポートします
  • dict のサブクラスにはしない方針が採られました。継承を許すとイミュータビリティを迂回でき、dict 本体の性能にも影響しうるためです

既存の types.MappingProxyType(3.3 で追加)との違いも PEP に整理されています。MappingProxyType はハッシュ不可で、継承もできず、元の辞書を取り出して書き換えることも容易でした。frozendict はその弱点を埋めるものです。

PEP 661: sentinel

「値が渡されなかったこと」を表すために _MISSING = object() と書くのは、Python の定番イディオムでした。3.15 では組み込みの sentinel() が使えます。

sentinel
MISSING = sentinel('MISSING')
 
def foo(value=MISSING):
    if value is MISSING:
        ...

sentinel() は位置専用引数の name(文字列)を取り、オプションで repr キーワード引数を受け付けます。object() では <object object at 0x000002825DF09650> のような読みにくい repr になっていたところが、次のように簡潔になります。

repr が読みやすくなる
>>> MISSING = sentinel('MISSING')
>>> MISSING
MISSING

PEP 798: 内包表記でのアンパック

内包表記とジェネレータ式の中で * と ** によるアンパックが書けるようになります。

内包表記でのアンパック
>>> lists = [[1, 2], [3, 4], [5]]
>>> [*L for L in lists]
[1, 2, 3, 4, 5]
 
>>> dicts = [{'a': 1}, {'b': 2}]
>>> {**d for d in dicts}
{'a': 1, 'b': 2}

これまで itertools.chain.from_iterable() や二重ループで書いていた「平坦化」が、1行で素直に表現できます。

PEP 799: profiling パッケージと Tachyon

プロファイリング関連が profiling パッケージに整理され、2つのサブモジュールが提供されます。

  • profiling.tracing: 決定的な関数呼び出しトレース
  • profiling.sampling: 統計的サンプリングプロファイラ Tachyon

Tachyon は最大 1,000,000 Hz という高頻度のサンプリングに対応し、壁時計時間・CPU・GIL 保持・例外といった複数のモードと、pstats / フレームグラフ / Firefox Profiler / ヒートマップといった出力形式を持ちます。async 対応のプロファイリングも可能です。

あわせて、従来の profile モジュールは非推奨となり、Python 3.17 で削除される予定です。

また PEP 831 により、CPython は フレームポインタを有効(-fno-omit-frame-pointer)にしてビルドされるようになります。perf などシステムレベルのプロファイラからスタックが正しく追えるようになる、という観測性の改善です。

free-threading の現在地

3.13 で実験的に導入され(PEP 703)、3.14 で「公式にサポートされる」段階に進んだ(PEP 779)free-threaded ビルドは、3.15 ではエコシステム側の整備が主題になります。

PEP 803 により、Stable ABI をターゲットにする C 拡張が free-threaded ビルド向け Stable ABI(abi3t) 向けにコンパイルできるようになりました。ただし abi3t を使うには、PEP 697 で導入された API(負の basicsize や PyObject_GetTypeData() など)への移行と、PyInit_ 関数から PEP 793 の新しいエクスポートフック PyModExport_* への切り替えが必要です。

公式ドキュメントは、Stable ABI が CPython の全機能を提供するわけではない点にも触れており、abi3t に移行できない拡張は従来どおり abi3 と free-threading 向けのバージョン固有 ABI(cp315t)を別々にビルドし続けることになります。

NOTE

free-threaded ビルドは 3.15 でもデフォルトのビルドではありません。通常の配布物は GIL ありのビルドで、free-threading を使うには専用ビルドを選ぶ必要があります。「3.15 で GIL が無くなる」ではない点に注意してください。

型システムとエラーメッセージ

型まわりでは3つの PEP が入ります。

  • PEP 728: TypedDict に「型付きの追加項目」を許す
  • PEP 747: TypeForm(型そのものを値として注釈する)
  • PEP 800: 型システムにおける互いに素な基底クラス(disjoint bases)

エラーメッセージの改善も継続しています。AttributeError の候補提示が改善され(他言語のメソッド名からの推測を含む)、delattr() の失敗時にも候補が出るようになりました。また対話シェル(PyREPL)では、補完候補がオブジェクトの種類に応じて色分けされ、from ... import でのモジュール属性の補完も効くようになります。argparse・ast・calendar・sqlite3・timeit など CLI の出力にも色が増えました。

削除・非推奨

移行時に確認しておきたい変更です。

  • __cached__ モジュール属性の削除: 3.13 で非推奨だったもので、import システムも標準ライブラリもこれを設定・参照しなくなりました。代わりに __spec__.cached を使います
  • profile モジュールの非推奨: 3.17 で削除予定。profiling.tracing へ移行します
  • re.match() / re.Pattern.match() のソフト非推奨: 名前が紛らわしいため、明示的な re.prefixmatch() / re.Pattern.prefixmatch() が導入されました。削除の予定はありません
  • PyGILState 系 C API のソフト非推奨: PyGILState_Ensure() / PyGILState_Release() などは削除予定こそないものの、今後新しい PyGILState API が追加されることはありません

このほか ast・ctypes・datetime・glob・http.server・importlib・pathlib・platform・sysconfig・threading・typing・wave などに、以前から非推奨だった API の削除が入っています。詳細な一覧は What's New in Python 3.15 の Removed セクションを参照してください。

NOTE

標準ライブラリの細かな削除項目については、本記事では個別の網羅までは確認できていません(要確認)。実際の移行時は -W error::DeprecationWarning を付けて 3.14 でテストを回し、警告を潰してから 3.15 に上げるのが確実です。

3.14 からの流れ

3.15 単体では分かりにくい変化も、直前の 3.14 と並べると方向性が見えます。3.14 では、アノテーションの遅延評価(PEP 649 / PEP 749)、標準ライブラリでの複数インタプリタ(PEP 734)、テンプレート文字列リテラル(t-string, PEP 750)、Zstandard 対応(PEP 784)、そして free-threaded Python の公式サポート(PEP 779)が入りました。

つまり 3.14 が「言語・実行モデルの拡張」だったのに対し、3.15 は lazy imports で起動を速くし、UTF-8 デフォルト化で環境差を消し、profiling パッケージとフレームポインタで計測しやすくするという、実行環境の整備に寄った版だと言えます。

なお 3.15 の What's New に t-string(PEP 750)関連の新セクションは見当たりませんでした。3.14 で入った機能がそのまま継続する形です。

移行チェックリスト

正式リリース後に 3.15 を試すなら、次の順で確認するとスムーズです。

  1. 3.14 で DeprecationWarning を潰す: python -W error::DeprecationWarning -m pytest でテストを回す
  2. エンコーディング依存を洗い出す: python -X warn_default_encoding -W error::EncodingWarning で encoding 未指定の I/O を特定し、明示的に指定する
  3. CP932 等を読むコードに encoding を明示する: UTF-8 デフォルト化で壊れる典型パターン
  4. __cached__ の参照を検索する: grep -rn "__cached__" して __spec__.cached に置き換える
  5. profile モジュールの利用箇所を確認する: profiling.tracing への移行計画を立てる
  6. lazy imports は起動時間を測ってから: python -X importtime でボトルネックの import を特定し、効果が見込める箇所に絞って lazy を付ける
  7. 依存ライブラリの 3.15 対応 wheel を確認する: rc2 以降 ABI 変更はないため、PyPI 上の cp315 wheel の有無が判断材料になります

バージョン管理そのものを整理したい場合は、pyenv から uv への移行も合わせて検討する価値があります。uv なら uv python install 3.15 のような形で 3.15 を隔離した環境に入れて試せます。データ分析まわりで試すなら、Jupyter Notebook 徹底解説で触れているカーネルの切り替えも使えます。

まとめ

  • Python 3.15 は 2026年10月1日リリース予定。2026年9月22日時点では 3.15.0rc2 の段階で、まだ正式リリースされていません
  • PEP 810 の lazy imports は起動時間の削減に効きますが、ImportError の発生タイミングが後ろにずれるという性質があります。CLI から局所的に導入するのが安全です
  • PEP 686 の UTF-8 デフォルト化は、Windows の CP932 問題を根本から解消する一方、CP932 を前提にしていたコードを壊します。encoding の明示が最善の備えです
  • frozendict・sentinel という定番イディオムの言語化、内包表記でのアンパック、profiling パッケージなど、地味に効く改善も揃っています
  • free-threading は 3.15 でもデフォルトではありません。3.15 の主題は abi3t によるエコシステム側の整備です

参考リンク

Node.jsが年1回のメジャーリリースへ - Node 27からの新スケジュールとLTSの考え方

Node.jsが年1回のメジャーリリースへ - Node 27からの新スケジュールとLTSの考え方

約7分

Node.js が 2026年3月の公式発表でリリーススケジュールを変更します。Node 27(2027年)から、メジャーは年1回(毎年4月)に集約され、奇数/偶数の区別を廃止して全リリースが LTS 対象に。早期テスト用の Alpha チャンネル新設、総サポート期間の36か月化など、新旧スケジュールの違いと、Node 26 / Node 27 の位置づけ、運用への影響を Node.js 公式ブログを一次ソースに整理します。

PHP バージョン履歴の歩き方 - PHP 5 から 8.5 までの変更点と追加機能を整理

PHP バージョン履歴の歩き方 - PHP 5 から 8.5 までの変更点と追加機能を整理

約15分

PHP のバージョン履歴を、各版の変更点と追加機能とともに整理します。PHP 5 系の OOP 整備、PHP 7 系のパフォーマンス革命と型、PHP 8 系のモダン化(JIT・enum・property hooks)まで。さらに 2025年11月リリースの PHP 8.5(パイプ演算子・clone with・URI 拡張)と PHP 8.4 の新機能を php.net の公式情報をもとにまとめ、サポート状況と移行の指針も示します。

Chrome が2週間ごとのリリースへ - Chrome 153 からの新サイクルと Web 開発・QA・企業IT への影響

Chrome が2週間ごとのリリースへ - Chrome 153 からの新サイクルと Web 開発・QA・企業IT への影響

約18分

Google Chrome は 2026年9月8日の Chrome 153 から、Stable と Beta のメジャーリリースを4週間ごとから2週間ごとへ切り替えました。Dev / Canary は変わらず、Extended Stable は8週間サイクルを維持します。公式ブログ・Chromium Dashboard・企業向けヘルプを一次ソースに、変更の経緯と理由、Chrome 160 までのスケジュール、Edge への波及、Playwright や Browserslist を使ったテスト運用、企業での更新管理への影響と対応チェックリストを整理します。