---
title: "Python 3.15の新機能｜遅延インポートとUTF-8既定化、3.14から上げる手順"
url: "https://www.issoh.co.jp/tech/details/18312/"
published: 2026-10-13
updated: 2026-10-13
categories: ["開発"]
publisher: "株式会社一創"
---

# Python 3.15の新機能｜遅延インポートとUTF-8既定化、3.14から上げる手順

Python 3.15.0は2026年10月9日に公開されました。目玉は `lazy import` による遅延インポート（PEP 810）と、encodingを省略した入出力がUTF-8になる既定化（PEP 686）の2つで、後者は日本語Windowsで動く業務コードの挙動を変えます。この記事では3.15の変更点をPEP番号つきで一覧にしたうえで、遅延インポートの書き方、UTF-8既定化で壊れる箇所の洗い出し、frozendictやTachyonプロファイラのコード例、3.14から上げてよい案件の線引きまでを順に扱う構成です。JITとフリースレッド版は[Python 3.14のJITコンパイラと新機能の記事](https://www.issoh.co.jp/tech/details/9409/)で扱っています。

## まとめ｜Python 3.15へ上げる前に決める文字コードと依存の二点

3.15への移行判断は、ほぼ次の2点で決まります。

1点目は**文字コードの扱い**。3.15では `open()` や `subprocess` のテキストモードでencodingを省略すると、OSのロケールに関係なくUTF-8で読み書きします。日本語WindowsでShift\_JIS（cp932）のCSVを省略形で読んでいたコードは、上げた瞬間に `UnicodeDecodeError` を出すか、文字化けしたファイルを書き出します。上げる前に `-X warn_default_encoding` で省略箇所を洗い出し、encodingを明示してください。

2点目は**依存ライブラリのwheel**。新規開発なら3.15を選んでかまいませんが、C拡張に依存する既存システムは、主要依存の3.15向けwheelが揃うまで3.14に据え置くのが安全です。3.14のバグ修正は2027年10月まで続きます。

## Python 3.15.0の公開日とサポート期限｜3.14・3.13との並び

3.15は年1回の定例マイナーリリースです。期限を押さえると上げる時期を逆算できます。

### 3.15.0は2026年10月9日公開、セキュリティ修正は2031年10月まで

[python.orgの3.15.0リリースページ](https://www.python.org/downloads/release/python-3150/)によると、公開日は2026年10月9日。3.14記事の執筆時点では10月1日予定でしたが、[リリース日程を定めるPEP 790](https://peps.python.org/pep-0790/)は最終的に10月9日（金）としています。以降は2か月ごとにバグ修正版が出て、3.17.0の公開前後に最後のバグ修正版、その後3年間はソース配布のみのセキュリティ修正という流れです。

| 系列   | 初版の公開      | バグ修正の終了             | サポート終了    |
| ---- | ---------- | ------------------- | --------- |
| 3.13 | 2024年10月7日 | 2026年10月1日（3.13.16） | 2029年10月頃 |
| 3.14 | 2025年10月7日 | 2027年10月予定（3.14.14） | 2030年10月頃 |
| 3.15 | 2026年10月9日 | 2028年10月頃（3.17公開時）  | 2031年10月頃 |

3.13は[PEP 719](https://peps.python.org/pep-0719/)、3.14は[PEP 745](https://peps.python.org/pep-0745/)の2026年10月13日時点の記載です。3.13はバイナリ付きの修正が終わり、3.12以前から上げる案件で経由する理由は薄れました。3.13固有の削除モジュールは[Python 3.13の新機能と3.12との違い](https://www.issoh.co.jp/tech/details/4042/)で整理しています。

### uv 0.13.0とRuff 0.17.0が同日公開で既定のPython版が変わった点

同じ10月9日に、周辺ツールも既定値を切り替えました。[uv 0.13.0のリリースノート](https://github.com/astral-sh/uv/releases/tag/0.13.0)は「既定の安定版Pythonを3.14から3.15に変更」を破壊的変更に挙げつつ、入っている互換版は引き続き使うと明記しています。

```
# uvを0.13.0以降に更新し、3.15を入れてプロジェクトに固定する
uv self update
uv python install 3.15
uv python pin 3.15
uv run python -VV
```

`uv python pin` が `.python-version` を書き換えるので、CIと手元の版が揃います。uvの使い方は[uvとは？Pythonの環境構築・パッケージ管理・バージョン管理の使い方を徹底解説](https://www.issoh.co.jp/tech/details/4384/)を参照してください。

Ruffは[0.17.0](https://github.com/astral-sh/ruff/releases/tag/0.17.0)で構文エラー判定の既定を3.15に上げましたが、`target-version` 未設定時の既定は3.11止まりです。**3.15の構文を使うなら pyproject.toml に版を書く**のが確実です（Ruffの設定全般は[PEP8とは？Pythonコーディング規約の基本ルールとチェックツール（Ruff対応）](https://www.issoh.co.jp/tech/details/3032/)）。

```
# pyproject.toml
[project]
requires-python = ">=3.15"

[tool.ruff]
target-version = "py315"
```

## Python 3.15の新機能一覧｜インタプリタ・標準ライブラリ・型の変更点

[What’s New in Python 3.15](https://docs.python.org/3.15/whatsnew/3.15.html)の冒頭に並ぶ変更を、業務コードへの影響が大きい順に並べ替えました。

### PEP番号で見るPython 3.15の主要変更10件と業務コードへの影響度

| PEP             | 変更内容                   | 既存コードへの影響      |
| --------------- | ---------------------- | -------------- |
| PEP 686         | 既定のエンコーディングがUTF-8      | 大（特にWindows）   |
| PEP 810         | lazy importによる遅延インポート  | なし（使うときだけ）     |
| PEP 799         | profilingパッケージとTachyon | 小（profileは非推奨） |
| PEP 814         | 組み込み型frozendict        | 小（dict判定の見直し）  |
| PEP 798         | 内包表記での\*と\*\*の展開       | なし             |
| PEP 661         | 組み込み型sentinel          | なし             |
| PEP 829         | パッケージ起動設定ファイル          | なし             |
| PEP 728・747・800 | TypedDict拡張・TypeFormほか | なし（型検査器側）      |
| PEP 803・820・793 | free-threaded向け安定ABI   | C拡張の作者のみ       |
| PEP 831         | フレームポインタを既定で有効         | C拡張のビルドのみ      |

上げただけで挙動が変わるのはPEP 686だけで、残りは使うと決めたときに効く追加機能かC拡張向けの変更です。PEP番号の無い変更には、実験的JITの強化、`AttributeError` で「`Did you mean '.append'?`」のように候補を示すエラーメッセージの改善、argparseの `suggest_on_error` の既定化、tomllibのTOML 1.1.0対応が入りました。

## lazy importで起動を短くする書き方と3.14以前との両立

遅延インポートは、読み込みを名前の初回使用まで先送りする仕組みです。起動時間が体感や課金に響くCLIやサーバーレス関数で効きます。

### lazy import・lazy fromの書き方とSyntaxErrorになる場所

[PEP 810](https://peps.python.org/pep-0810/)は `lazy` をソフトキーワードとして追加しました。`import` 文と `from` 文の前に置いたときだけ意味を持ち、変数名としての `lazy` はそのまま使えます。

```
lazy import json
lazy from pathlib import Path

print("起動完了")          # この時点では json も pathlib も読み込まれていない

data = json.loads('{"key": "value"}')   # ここで json が読み込まれる
p = Path(".")                            # ここで pathlib が読み込まれる
```

使える場所はモジュールの最上位だけです。関数の中、クラス本体、`try`・`except`・`finally` の中に書くとコンパイル時に `SyntaxError` になり、`lazy from x import *` と `lazy from __future__ import ...` も同じく拒否されます。オプション依存を `try: import` で吸収している既存コードは、その部分だけ遅延の対象外です。

### \-X importtimeで起動時間を測り遅延対象を決める手順

全部を `lazy` にする必要はありません。読み込みに時間がかかっているモジュールを測ってから、上位だけを遅延させます。

```
# 1. どのモジュールの読み込みが重いかを記録する（標準エラーに出る）
python -X importtime -c "import myapp.cli" 2> importtime.log

# 2. 全インポートを遅延扱いにした場合の起動時間と比べる
python -X lazy_imports=all -m myapp.cli --help
python -X lazy_imports=none -m myapp.cli --help
```

`-X lazy_imports`（環境変数 `PYTHON_LAZY_IMPORTS`）の値は、`normal`（既定。`lazy` 付きだけ遅延）、`all`（最上位の全インポートを遅延）、`none`（すべて即時）の3つ。`all` で速くなりテストも通るなら、重い上位数モジュールに `lazy` を付ける根拠になり、`none` は不具合の切り分けに使えます。

### \_\_lazy\_modules\_\_で3.14以前と同じコードを動かす互換の書き方

3.14と3.15の両方で動かすライブラリでは、3.14以前のパーサが構文エラーを出すため `lazy` キーワードを使えません。互換の手段が `__lazy_modules__` です。

```
__lazy_modules__ = ["json", "pathlib"]

import json      # 3.15では遅延、3.14以前では通常のインポート
import os        # リストに無いので即時
```

3.14以前ではただの変数として無視されるため、同じファイルがどちらの版でも動きます。**両対応が必要なコードは `__lazy_modules__`、3.15専用のアプリは `lazy` キーワード**と使い分けるのが実務上の線です。

### ImportErrorが初回使用時に移る副作用と遅延させない依存

遅延インポートでは、`ImportError` や `ModuleNotFoundError` が名前を最初に使った時点まで先送りされます。依存の入れ忘れが、起動直後ではなく、その機能を初めて呼んだリクエストで表面化します。

だからWebアプリ本体のDBドライバや認証ライブラリは遅延させないでください。デプロイ直後のヘルスチェックで落ちたほうが切り分けが早く済みます。遅延に向くのは、CLIのサブコマンドでしか使わない重い依存（pandas、boto3など）や一部画面だけの帳票ライブラリです。遅延中のモジュールは `sys.modules` に現れないため、読み込み状態で分岐する既存コードも確認が要ります。

## UTF-8既定化（PEP 686）でWindowsの業務コードが壊れる箇所

何もしなくても挙動が変わる唯一の変更です。[PEP 686](https://peps.python.org/pep-0686/)自身、影響の中心はWindowsだと書いています。

### encoding省略のopenとCSV入出力がcp932から変わる影響範囲

3.14までの日本語Windowsでは、encoding省略の `open()` はcp932で読み書きしていました。3.15ではファイル・標準入出力・パイプの既定がUTF-8に揃います。

| 書き方                  | 3.14（日本語Windows） | 3.15        |
| -------------------- | ---------------- | ----------- |
| open(path) で読む       | cp932            | UTF-8       |
| open(path, “w”) で書く  | cp932            | UTF-8       |
| subprocessのtext=True | cp932            | UTF-8       |
| encoding=”locale” 指定 | cp932            | cp932（変化なし） |

壊れ方は2種類あります。会計ソフトや基幹システムが出力したShift\_JISのCSVを省略形で読むと、読み込みの時点で `UnicodeDecodeError` が発生するケースです。逆に、Excelで開く前提のCSVを省略形で書いていた処理は例外を出さずにUTF-8（BOMなし）で書き出し、受け取った側のExcelで文字化けします。**後者は例外が出ないぶん、気付くのが遅れます。**

### \-X warn\_default\_encodingで省略箇所を洗い出す手順

PEP 686が勧める手順は、いったんUTF-8モードを切った状態で、encoding省略の警告を出してテストを回すやり方です。

```
# 3.14以前と同じ挙動に戻し、encoding省略箇所をEncodingWarningで洗い出す
python -X utf8=0 -X warn_default_encoding -m pytest

# 警告を例外にして、省略箇所でテストを落とす
python -X utf8=0 -X warn_default_encoding -W error::EncodingWarning -m pytest
```

検出した箇所は、外部から受け取るファイルなら実際の文字コード（`encoding="cp932"` など）、自社で完結するファイルなら `encoding="utf-8"`、OSの設定に従わせたい箇所だけ `encoding="locale"` と書き分けます。どうしても間に合わない場合は環境変数 `PYTHONUTF8=0` で従来挙動に戻せますが、これは移行までのつなぎです。

```
# 3.15では省略時にUTF-8で読むため、Shift_JISのCSVは文字コードを明示する
import csv

with open("uriage.csv", encoding="cp932", newline="") as f:
    rows = list(csv.reader(f))
```

### subprocessのtext=Trueとロケール取得関数を書き換える箇所

見落としやすいのは `subprocess.run(..., text=True)` です。`ipconfig` や古い社内バッチなどcp932で出力するコマンドをテキストモードで受けると、文字化けか例外になります。PEP 686は `encoding="utf-8"` か `encoding="locale"` への置き換えを案内しています。

`locale.getpreferredencoding()` もUTF-8モードの影響を受け、3.15ではロケールに関係なくUTF-8を返すようになります。ロケール本来の文字コードが必要な処理は、3.11で追加された `locale.getencoding()` に置き換えてください。

## frozendictと内包表記アンパックを3.15の実コードで試す書き方

ここからは書き手が選んで使う追加機能です。既存コードを書き換えるより、新しく書くコードから入れるほうが無理がありません。

### frozendictで設定値を不変にする書き方とisinstance判定の見直し

[PEP 814](https://peps.python.org/pep-0814/)で追加された `frozendict` は、変更できない辞書型です。キーと値がすべてハッシュ可能なら、それ自体もハッシュ可能になります。

```
>>> settings = frozendict(timeout=30, retries=3)
>>> settings["timeout"] = 60
TypeError: 'frozendict' object does not support item assignment
>>> cache = {settings: "結果"}          # 辞書のキーにもできる
>>> frozendict(retries=3, timeout=30) == settings
True
```

注意点は継承関係です。`frozendict` は `dict` のサブクラスではないため、`isinstance(arg, dict)` で判定する関数は弾きます。What’s Newは `(dict, frozendict)` か `collections.abc.Mapping` への拡張を勧めています。使いどころはモジュール定数の設定値や、関数の既定引数に置く辞書です。

### 内包表記の\*と\*\*展開でネストしたリストと辞書を平坦にする書き方

[PEP 798](https://peps.python.org/pep-0798/)により、内包表記の要素に `*` と `**` を書けるようになりました。二重ループで書いていた平坦化が1段で済みます。

```
>>> lists = [[1, 2], [3, 4], [5]]
>>> [*L for L in lists]            # [x for L in lists for x in L] と同じ
[1, 2, 3, 4, 5]
>>> dicts = [{"a": 1}, {"b": 2}, {"a": 3}]
>>> {**d for d in dicts}           # 後勝ちでマージ
{'a': 3, 'b': 2}
```

辞書の展開は後ろの値で上書きされるため、設定の重ね合わせのように「後勝ち」が意図どおりの場面に向きます。キーの衝突を検出したい処理には使えません。

## Tachyonサンプリングプロファイラで本番プロセスを計測する手順

PEP 799で新設された `profiling` パッケージは、決定的トレースの `profiling.tracing`（旧 `cProfile`）と、統計サンプリングの `profiling.sampling`（通称Tachyon）の2つで構成されます。`cProfile` は互換の別名として残り、`profile` モジュールは3.17で削除予定です。

### profiling.samplingのrunとattachでフレームグラフを出すコマンド

Tachyonは一定間隔でスタックを読み取る方式で、動作中のプロセスを止めずに外から計れる点が `cProfile` との違いです。[profiling.samplingのドキュメント](https://docs.python.org/3.15/library/profiling.sampling.html)に載っている形で並べます。

```
# スクリプトを起動しながら計測し、フレームグラフをHTMLで出す
python -m profiling.sampling run --flamegraph -o profile.html script.py

# 動作中のプロセス（PID 12345）に30秒だけ取り付けて計測する
python -m profiling.sampling attach --flamegraph -d 30 -o profile.html 12345

# 端末上でリアルタイムに表示する（Unix系のみ・qで終了）
python -m profiling.sampling attach --live 12345
```

フレームグラフは外部依存の無い1枚のHTMLです。サンプリング頻度は最大1,000,000Hz、計測モードは `--mode wall`（既定）のほか `cpu`・`gil`・`exception` を選べます。「CPUは空いているのに遅い」ならwall、「スレッドを増やしても速くならない」ならgilから見ると原因に早く当たります。

### attachに必要なOS別の権限とマイナーバージョン一致の制約

attachは他プロセスのメモリを読むため、OSごとに権限が要ります。Linuxは root、`CAP_SYS_PTRACE`、Yamaの `ptrace_scope` 調整のいずれか。macOSは root かデバッガ用entitlement、Windowsは管理者権限か `SeDebugPrivilege` です。コンテナ内のプロセスに当てるなら、`SYS_PTRACE` を付けるかをセキュリティ方針と合わせて先に決めます。

プロファイラと対象は同じマイナーバージョンでなければならず、3.15のTachyonから3.14のプロセスには取り付けられません。**本番を3.14に据え置く間は、Tachyonの恩恵は受けられない**と割り切ってください。

## 3.14から3.15へ上げる前に確認する削除API・ビルド・JITの変更

### 3.15で削除されたAPI一覧とsre\_\*・CGI・load\_moduleの置き換え先

| 削除されたもの                  | 置き換え先                |
| ------------------------ | -------------------- |
| sre\_compile・sre\_parse等 | re モジュール             |
| CGIHTTPRequestHandler    | WSGI等の別実装            |
| Loader.load\_module()    | exec\_module()       |
| PurePath.is\_reserved()  | os.path.isreserved() |
| platform.java\_ver()     | なし                   |
| codeobject.co\_lnotab    | co\_lines()          |
| NamedTupleのキーワード構文       | クラス構文                |
| \_\_cached\_\_ 属性        | \_\_spec\_\_.cached  |

業務コードで当たりやすいのは、`python -m http.server --cgi` で社内向けCGIを動かすケースと、古いプラグイン機構の `load_module()` です。年を含まない書式で `%d` を使う `datetime.strptime()` も `ValueError` になるため、月日だけの文字列は年を補ってから渡します。

### フレームポインタ既定化とabi3tがC拡張のビルドに与える影響

PEP 831でCPython本体が `-fno-omit-frame-pointer` 付きでビルドされ、このフラグは `sysconfig` 経由で拡張モジュールにも伝わります。独自のビルドスクリプトでCFLAGSを上書きしている場合は、引き継ぎを確認してください。

free-threadedビルド向けには、PEP 803・820・793で安定ABI（`abi3t`）が用意され、C拡張の配布者は版ごとのwheelの作り分けが減ります。

### 実験的JITの7〜12%高速化を3.14の実測と並べて読む注意点

What’s Newは、JITがx86-64 Linuxで7〜8%、AArch64 macOSで11〜12%速い（pyperformance幾何平均）と報告しています。ただし3.15でもJITは実験的で既定は無効です。Intel Macでの実測では処理によって遅くなる例も出ており、手順と数値は[Python 3.14のJIT記事](https://www.issoh.co.jp/tech/details/9409/)に譲ります。JITを理由に上げる判断は、自分の処理で測るまで保留が妥当です。

## 受託案件でPython 3.15を採用する条件と見送るべき案件

### 新規開発で3.15を選ぶ条件｜依存wheelとCIの二つの確認

新規開発は、次の2つが確認できれば3.15で始めてかまいません。

1. 主要依存（NumPy・pandas・DBドライバなど）のPyPIのファイル一覧に、3.15向けのwheel（ファイル名に `cp315`）が対象OS・CPU分そろっている
2. CIのマトリクスに3.15を加え、テストが `-W error::EncodingWarning` 付きで通る

新規なら最初からencodingを明示して書けるので、UTF-8既定化はむしろ追い風です。1つ目が満たせない場合は、3.14で始めて半年後に上げるほうが、ソースビルド環境を抱えるより安く済みます。

### Windowsで動く既存の業務バッチを3.14に据え置く三つの条件

次のいずれかに当たる既存システムは、2026年中は3.14に据え置きます。

- 日本語WindowsでShift\_JISのCSVや外部コマンドの出力を、encoding省略で扱っている
- テストが薄く、`-X warn_default_encoding` を回しても省略箇所を網羅できない
- C拡張を含む依存が3.15向けwheelを出していない

1つ目と2つ目が重なる案件は、版上げより先に文字コードの棚卸しとテスト整備が必要です。3.14のバグ修正は2027年10月まで続くので、2027年前半に3.15か3.16へ移す計画で十分間に合います。古いPythonで動き続けている業務システムの更新を、文字コードやOSの移行と合わせて進める場合は、[システムマイグレーション・リプレイス](https://www.issoh.co.jp/service/system/migration/)で既存資産の調査から相談を受け付けています。

## よくある質問

Python 3.15について検索されることの多い質問をまとめました。

### Python 3.15はいつリリースされましたか？

3.15.0は2026年10月9日（金）に公開されました。以降は2か月ごとにバグ修正版が出て、バグ修正は2028年10月頃まで、ソース配布のみのセキュリティ修正は2031年10月頃まで続く予定です。

### Python 3.15に上げると既存のコードは動かなくなりますか？

多くのコードはそのまま動きます。危ないのは日本語Windowsでencodingを省略してファイルや外部コマンドの出力を扱うコードで、cp932ではなくUTF-8で読み書きするため例外や文字化けが起きます。`sre_compile` などの削除モジュールや `http.server` の `--cgi` を使う箇所も書き換えが必要です。

### lazy importはPython 3.14以前でも使えますか？

構文としての `lazy import` は3.15からで、3.14以前ではエラーになります。両方の版で動かすなら、モジュール名を `__lazy_modules__` に並べる書き方が選択肢です。3.14以前ではただの変数として無視されるので、同じファイルのまま両対応できます。

### Python 3.14と3.15はどちらを使えばよいですか？

主要な依存ライブラリが3.15向けwheelを出している新規開発なら3.15、Shift\_JISのファイルを扱う既存のWindows業務システムなら文字コードの棚卸しが済むまで3.14、という分け方が安全です。3.14のバグ修正は2027年10月まで続きます。

### uvでPython 3.15を入れるにはどうすればよいですか？

`uv self update` でuvを0.13.0以降に更新し、`uv python install 3.15` で導入、`uv python pin 3.15` でプロジェクトの版を固定します。0.13.0で既定の安定版は3.15に変わりましたが、入っている互換版は引き続き使われるため、既存プロジェクトの版は自動では上がりません。

## 関連記事

- [Python 3.14のJITコンパイラとは？有効化の手順と実測、フリースレッド版と新機能](https://www.issoh.co.jp/tech/details/9409/)：JITの有効化手順と3.15.0rc2までの実測
- [Python 3.13の新機能と3.12との違い｜GIL無効化の実測・削除モジュール・サポート期限](https://www.issoh.co.jp/tech/details/4042/)：3.13で削除されたモジュールと期限
- [uvとは？Pythonの環境構築・パッケージ管理・バージョン管理の使い方を徹底解説](https://www.issoh.co.jp/tech/details/4384/)：3.15の導入と版固定に使うツールの基本
- [pyenvでPythonのバージョンを切り替える手順｜shimの仕組みとビルド失敗の対処](https://www.issoh.co.jp/tech/details/17513/)：3.14と3.15を並べて入れる別の方法
- [Poetryとは？Python依存管理の仕組みと2.5系の使い方・uvとの選び方](https://www.issoh.co.jp/tech/details/12303/)：requires-pythonの管理と依存解決

---

出典: [Python 3.15の新機能｜遅延インポートとUTF-8既定化、3.14から上げる手順](<https://www.issoh.co.jp/tech/details/18312/>)（株式会社一創）
