- Python
Python 3.15の新機能と変更点|3.15.0を入れて3.14と実測比較
結論
Python 3.15 は 2026年10月9日に出た最新の安定版で、目玉は lazy import(遅延インポート)・frozendict・sentinel・内包表記のアンパック・UTF-8 のデフォルト化です。いちばん影響が大きいのは UTF-8 のデフォルト化で、encoding を書いていない open() や subprocess の読み書きの結果が変わります。
この記事でわかること
- 3.15.0 を uv で入れて新機能を1つずつ動かした出力
- 起動時間・JIT・フリースレッドを 3.14 と比べた実測
- 3.14 から上げると壊れる14項目のエラー原文と直し方
この記事で実際に動かしたもの:uv 0.13.7 で入れた CPython 3.15.0(通常版とフリースレッド版)と 3.14.10 で、新機能・削除された API・エラーメッセージ・起動時間・JIT・スレッドの速さを同じスクリプトで比べました。
flowchart TD
A[3.15に上げたい] --> B{使うパッケージに<br>cp315 の wheel?}
B -->|無い| W[3.14のまま待つ]
B -->|ある| C{encoding 無しの<br>open・subprocess?}
C -->|ある| E[encoding を明記]
C -->|無い| D{削除された<br>APIを使う?}
E --> D
D -->|使う| F[置き換える]
D -->|使わない| G[3.15.2 で試す]
F --> G
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| Python 3.15 はいつ出た? | 3.15.0 が 2026年10月9日。3.15.2 が最新(10月26日) | Python 3.15とは |
| Python 3.15 の新機能は? | lazy import・frozendict・sentinel・内包表記の * と ** | 新機能の各節 |
| 3.14 との違いで困る点は? | UTF-8 のデフォルト化と、3.13〜3.14 で非推奨だった API の削除 | UTF-8・移行で壊れる点 |
| Python 3.15 のインストール方法 | uv python install 3.15。Windows は py install 3.15 |
インストール |
| uv で 3.15 が見つからない | uv が以前の版。uv 自体を更新する | インストール |
| 速くなった? | 公式値は JIT で 7〜8%。手元の小さな計測では JIT 有効で 0〜22% 短縮、遅くなる処理もあった | JITとフリースレッド |
| numpy・pandas は動く? | 2026年11月5日時点で cp315 の wheel が入り、動いた | インストール |
| 今すぐ上げるべき? | 新規は 3.15.2 で開始。既存は wheel と encoding を確かめてから | 判断表 |
確認環境:Ubuntu 24.04.5 LTS(x86-64・2 CPU)の上で、PyPI から入れた uv 0.13.7 を作業用の venv に置き、UV_CACHE_DIR・UV_PYTHON_INSTALL_DIR を作業場所に向けて CPython 3.15.0(python-build-standalone の配布物)を入れました。python -VV の表示は Python 3.15.0 (main, Oct 14 2026, 01:05:07) [Clang 23.1.3 ] です。比較には同じ方法で入れた 3.14.10、フリースレッド版の 3.15.0t、OS の 3.13.18 を使い、元から入っていた uv 0.11.32 の挙動も確かめています。スクリプトは env -i で環境変数を空にして LANG=C.UTF-8 で実行し、文字コードの比較だけは作業場所に作った ja_JP.eucJP のロケールで動かしました。numpy 2.5.4・pandas 3.1.1・pydantic 2.14.2 は 3.15.0 の仮想環境に入れて読み込みを確かめています。新機能・削除・非推奨の中身は Python 公式の「What's New In Python 3.15」(CPython のリポジトリにある原稿)と PEP 790・各 PEP、リリース日は python.org のリリースページ、Windows の手順は公式ドキュメント「Using Python on Windows」、uv の仕様は uv 公式ドキュメントで確かめました。Windows・macOS での操作と、JIT の公式の性能値(pyperformance)は公式の範囲です。図は mermaid 11.16.0 で描画を確かめています(確認日 2026年11月5日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Python 3.15の新機能と変更点|3.15.0を入れて3.14と実測比較」
Python 3.15とは(リリース日・サポート期間・入手方法)
この節では、Python 3.15 が何で、いつ出て、いつまで直してもらえるのかが1枚の表で分かります。
Python 3.15 は、2026年10月9日に正式版(3.15.0)が出た Python の最新の安定版です。 リリース候補版を3回(8月4日・9月1日・10月2日)出したうえでの公開で、その後、10月21日に 3.15.1、10月26日に 3.15.2 が出ています。費用はかからず、python.org・各 OS のパッケージ・uv などから入手できます。
| 項目 | 内容 |
|---|---|
| 何が | CPython 3.15(言語・標準ライブラリ・インタープリターの新しい版) |
| いつ | 3.15.0:2026年10月9日/3.15.1:10月21日/3.15.2:10月26日(PEP 790) |
| 誰に | Python を使う全員。Windows 64bit 版はテールコール型インタープリター、macOS 版はフリースレッド版も標準で入る |
| いくらで | 無料(PSF ライセンス) |
| バグ修正 | およそ2か月ごとに2年間(3.17.0 のころまで) |
| セキュリティ修正 | 2031年10月ごろまで(ソースのみ) |
| リリースマネージャー | Hugo van Kemenade |
3.15.2 では、3.15.0 で入った「複数のスレッドが同時に import package.submodule するとデッドロックしうる」退行が直り、ssl が侵害された認証局(eMudhra)の中間証明書を拒否するようになりました。この記事の動作確認は 3.15.0 ですが、これから使い始めるなら 3.15.2 を選ぶのが確実です。
大きな変更は次の3つにまとめられます。
1書き方が増えた
lazy import、組み込みの frozendict・sentinel、[*L for L in lists] のような内包表記のアンパック。
2既定の動きが変わった
encoding を省いた入出力が UTF-8 に。3.13〜3.14 で警告が出ていた API が削除され、エラーになる。
3道具と速さ
サンプリングプロファイラー Tachyon(profiling.sampling)、JIT の強化、フリースレッド版の安定 ABI(abi3t)。
Python 3.15のインストール(uvで3.15.0を入れる)
この節では、uv で Python 3.15 を入れる手順と、uv が 3.15 を見つけられないときの原因が分かります。
uv を新しくする
uv は配布される Python の一覧を本体に持っている。3.15.0 が出る前の uv は 3.15.0 を知らない。
版を指定して入れる
uv python install 3.15 で最新のパッチ版、3.15.0 なら版を固定。フリースレッド版は 3.15t。
版を確かめる
python3.15 -VV でビルド日とコンパイラーまで出る。
プロジェクトで使う
uv init --python 3.15 か uv python pin 3.15。.python-version に書かれる。
以前の uv では 3.15.0 が見つからない
このマシンに元から入っていた uv 0.11.32 で 3.15 を探すと、ベータ4までしか出てきません。
$ uv --version
uv 0.11.32 (x86_64-unknown-linux-gnu)
$ uv python list 3.15 --all-versions
cpython-3.15.0b4-linux-x86_64-gnu <download available>
$ uv python install 3.15.0
error: No download found for request: cpython-3.15.0-linux-x86_64-gnu
uv の公式ドキュメントには「入れられる Python の版は uv のリリースごとに固定されている」とあり、新しい版を入れるには uv の更新が要ります。 PyPI の最新版(0.13.7)を作業用の venv に入れると、3.15.0〜3.15.2 が並びました。
$ python3 -m venv /dev/shm/t281/uvenv
$ /dev/shm/t281/uvenv/bin/pip install uv
$ export UV_CACHE_DIR=/dev/shm/t281/uvcache UV_PYTHON_INSTALL_DIR=/dev/shm/t281/py
$ uv --version
uv 0.13.7 (x86_64-unknown-linux-gnu)
$ uv python list 3.15 --all-versions
cpython-3.15.2-linux-x86_64-gnu <download available>
cpython-3.15.1-linux-x86_64-gnu <download available>
cpython-3.15.0-linux-x86_64-gnu <download available>
$ uv python install 3.15.0
Downloading cpython-3.15.0-linux-x86_64-gnu (download) (35.9MiB)
Downloaded cpython-3.15.0-linux-x86_64-gnu (download)
Installed Python 3.15.0 in 1.74s
+ cpython-3.15.0-linux-x86_64-gnu (python3.15)
$ /dev/shm/t281/py/cpython-3.15.0-linux-x86_64-gnu/bin/python3.15 -VV
Python 3.15.0 (main, Oct 14 2026, 01:05:07) [Clang 23.1.3 ]
ダウンロードは 35.9MiB、展開後は 112MB でした。注意点として、uv python install は UV_PYTHON_INSTALL_DIR を変えても、実行ファイルへのリンク(python3.15)を ~/.local/bin に作ります。 公式ドキュメントにも「既定で PATH に実行ファイルを入れる」とあります。今回はホームを汚さないよう作ったリンクを消し、以後は UV_PYTHON_BIN_DIR を作業場所に向けました。試すだけの環境では、この変数も一緒に指定しておくと片付けが楽です。
プロジェクトを 3.15 で作る
$ uv init --python 3.15 demo
Initialized project `demo` at `/srv/s4/r17/t281/proj/demo`
$ cd demo && cat .python-version
3.15
$ grep requires pyproject.toml
requires-python = ">=3.15"
requires = ["uv_build>=0.13.7,<0.14.0"]
$ uv run demo
Hello from demo!
$ uv python pin 3.15.0
Updated `.python-version` from `3.15` -> `3.15.0`
$ uv run python -VV
Python 3.15.0 (main, Oct 14 2026, 01:05:07) [Clang 23.1.3 ]
requires-python = ">=3.15" になるので、チームに 3.14 の人がいる場合は範囲を広げるかどうかを先に決めます。
Windows・macOS・pyenv の場合(公式の範囲)
| 環境 | 入れ方 | 補足 |
|---|---|---|
| Windows | py install 3.15(Python install manager) |
フリースレッド版は py install 3.15t、起動は py -V:3.15。従来のインストーラーも 3.15 までは配布(非推奨) |
| macOS | python.org の python-3.15.0-macos11.pkg |
フリースレッド版も既定で入る。macOS 27.0 では IDLE など tkinter のダイアログが固まる件が告知されている |
| Linux・各 OS | uv python install 3.15 |
この記事で確かめた方法。OS のパッケージは配布元しだい |
主要ライブラリは 3.15 で動くか
3.15.0 の仮想環境に numpy・pandas・pydantic を入れると、どれも cp315 用の wheel がそのまま入り、ビルドは起きませんでした(2026年11月5日時点)。
$ uv venv --python 3.15.0 /dev/shm/t281/venv315
Using CPython 3.15.0
$ uv pip install numpy pandas pydantic
+ numpy==2.5.4
+ pandas==3.1.1
+ pydantic==2.14.2
+ pydantic-core==2.50.2
...
$ grep Tag numpy-2.5.4.dist-info/WHEEL
Tag: cp315-cp315-manylinux_2_27_x86_64
Tag: cp315-cp315-manylinux_2_28_x86_64
$ python -c 'import numpy as np, pandas as pd, pydantic, sys; print(sys.version.split()[0], np.__version__, pd.__version__, pydantic.VERSION)'
3.15.0 2.5.4 3.1.1 2.14.2
C 拡張を含むパッケージは、cp315 の wheel が無いと手元でのビルドになり、コンパイラーが無い環境では入りません。 上げる前に uv pip install --python 3.15 -r requirements.txt を試すのが早い確かめ方です。uv の基本的な使い方は、関連記事「uv venvとuvの使い方|仮想環境の作成・有効化とpipとの速さ比較」で扱っています。
新機能1:lazy import(遅延インポート・PEP 810)
この節では、lazy import の書き方と、起動時間がどれだけ変わるかの実測が分かります。
lazy import は、モジュールの読み込みを「その名前を最初に使ったとき」まで遅らせる書き方です。 lazy はソフトキーワードなので、lazy という変数名は今までどおり使えます。
import sys
lazy import json
lazy from pathlib import Path
print("json in sys.modules:", "json" in sys.modules)
print("type of name json:", type(globals()["json"]).__name__)
data = json.loads('{"key": "value"}')
print("after use:", "json" in sys.modules, data)
print(sys.get_lazy_imports())
$ python3.15 f_lazy.py
json in sys.modules: False
type of name json: lazy_import
after use: True {'key': 'value'}
normal
$ python3.14 f_lazy.py
File "/srv/s4/r17/t281/w/f_lazy.py", line 2
lazy import json
^^^^^^
SyntaxError: invalid syntax
宣言の直後、json という名前には lazy_import 型の代理オブジェクトが入っていて、json.loads を呼んだ時点で本物のモジュールが読み込まれます。3.14 では文法エラーなので、3.14 と共存させるコードには lazy を書けません。
起動時間の実測
引数が無いときは使い方を表示するだけの小さな CLI に、asyncio・email・http.client・decimal・argparse・json・xml・sqlite3・unittest を先頭で import しました。同じ中身を import と lazy import で書き分け、21回ずつ起動した中央値です。
| 起動のしかた(3.15.0) | 中央値 | 最小〜最大 |
|---|---|---|
python -c pass(何もしない) |
12.7ms | 12.0〜20.8ms |
通常の import で9モジュール |
97.0ms | 88.5〜127.4ms |
lazy import で9モジュール |
12.7ms | 12.0〜19.5ms |
通常の import + -X lazy_imports=all |
12.7ms | 11.8〜18.0ms |
lazy import で、json を実際に使う |
23.3ms | 20.0〜42.1ms |
-X importtime の出力も、通常の import では213行、lazy では27行(ほぼ site の分だけ)でした。使わないモジュールの読み込み時間がそのまま消えるので、サブコマンドの多い CLI やテストの収集で効きます。 処理時間の測り方そのものは、関連記事「Python処理時間の計測方法|perf_counter・timeit比較とコピペ集」で扱っています。
書けない場所とエラーの原文
$ python3.15 f_lazy_bad.py # 関数の中
SyntaxError: lazy import not allowed inside functions
$ python3.15 f_lazy_bad2.py # try の中
SyntaxError: lazy import not allowed inside try/except blocks
$ python3.15 f_lazy_bad3.py # lazy from os import *
SyntaxError: lazy from ... import * is not allowed
モジュールの一番外側でしか使えません。try: import yaml except ImportError: のような「無ければ別の手」は、lazy にできない書き方です。
読み込みの失敗は「使った行」で起きる
$ python3.15 f_lazyerr.py
start OK
Traceback (most recent call last):
File "/srv/s4/r17/t281/w/f_lazyerr.py", line 1, in <module>
lazy import yaml_not_installed
ImportError: lazy import of 'yaml_not_installed' raised an exception during resolution
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/srv/s4/r17/t281/w/f_lazyerr.py", line 5, in <module>
main()
~~~~^^
File "/srv/s4/r17/t281/w/f_lazyerr.py", line 4, in main
return yaml_not_installed.safe_load("a: 1")
^^^^^^^^^^^^^^^^^^
ModuleNotFoundError: No module named 'yaml_not_installed'
無いモジュールを lazy にしても起動は通り(start OK)、使った行で ModuleNotFoundError になります。トレースバックには import の行と使った行の両方が出ます。「起動時に依存の欠けを見つける」役目を import が持っていた場合、lazy にするとその確認が遅れる点に注意します。 import の基本とエラーの見方は、関連記事「Python importの使い方|自作モジュールとエラー対処」で扱っています。
3.14 と共存させる:__lazy_modules__
import sys
__lazy_modules__ = ["json"]
import json
import os
print(sys.version_info[:2], "json" in sys.modules, "os" in sys.modules)
$ python3.15 f_lazymods.py
(3, 15) False True
$ python3.14 f_lazymods.py
(3, 14) True True
__lazy_modules__ に名前を書くと、普通の import json が 3.15 では lazy になり、3.14 では通常どおり読み込まれます。両方の版で動かすライブラリはこの書き方が向いています。ほかに、sys.set_lazy_imports_filter() で「自分のパッケージだけ lazy」のような指定もできます。
新機能2:frozendict と sentinel(組み込み型の追加)
この節では、組み込みに加わった frozendict(PEP 814)と sentinel(PEP 661)の使いどころが、実行結果で分かります。
from collections.abc import Mapping
import copy, json
a = frozendict(x=1, y=2)
b = frozendict(y=2, x=1)
print(repr(a), a == b, hash(a) == hash(b), list(b))
print("dict subclass?", isinstance(a, dict), "| Mapping?", isinstance(a, Mapping))
cache = {frozendict(host="db1", port=5432): "conn-1"}
print(cache[frozendict(port=5432, host="db1")])
print(a | {"z": 3})
print(json.dumps(a))
cfg = json.loads('{"a": [1, 2, {"b": [3]}]}', object_pairs_hook=frozendict, array_hook=tuple)
print(cfg)
a["z"] = 3
frozendict({'x': 1, 'y': 2}) True True ['y', 'x']
dict subclass? False | Mapping? True
conn-1
frozendict({'x': 1, 'y': 2, 'z': 3})
{"x": 1, "y": 2}
frozendict({'a': (1, 2, frozendict({'b': (3,)}))})
TypeError: 'frozendict' object does not support item assignment
frozendict は変更できない辞書で、中身がハッシュ可能なら辞書のキーや set の要素にできます。 並び順は保ちますが、比較では順番を見ません。json.loads の新しい引数 array_hook=tuple と組み合わせると、設定ファイルを丸ごと変更できない形で読めます。値にリストを入れると hash() で TypeError: unhashable type: 'list' になります。
型の判定で起きる違い
公式の What's New も isinstance(arg, (dict, frozendict)) か Mapping への書き換えを案内している
sentinel:「値が無い」を表す専用の値
MISSING = sentinel("MISSING")
print(repr(MISSING), type(MISSING).__name__, copy.deepcopy(MISSING) is MISSING, bool(MISSING))
def get(d, k, default=MISSING):
v = d.get(k, MISSING)
if v is MISSING:
if default is MISSING: raise KeyError(k)
return default
return v
print(get({"a": None}, "a"), get({}, "b", 0))
print(int | MISSING)
MISSING sentinel True True
None 0
int | MISSING
None も正しい値になりうる引数の「省略された」を区別するときに使います。 これまでの _MISSING = object() と違い、repr が MISSING と読みやすく、コピーしても同じものが返り(deepcopy(...) is MISSING が True)、int | MISSING のように型の式にも書けます。真偽値は True なので、if not value: ではなく is MISSING で比べます。型ヒントの書き方全体は、関連記事「Pythonの型ヒントの書き方|3.12以降の新しい書き方まで」で扱っています。
新機能3:内包表記のアンパック(* と **・PEP 798)
この節では、内包表記で * と ** が使えるようになった書き方と、3.14 で出るエラーが分かります。
lists = [[1, 2], [3, 4], [5]]
print([*L for L in lists])
print({*s for s in [{1, 2}, {2, 3}]})
print({**d for d in [{'a': 1}, {'b': 2}, {'a': 3}]})
print(list((*L for L in lists)))
$ python3.15 unpack.py
[1, 2, 3, 4, 5]
{1, 2, 3}
{'a': 3, 'b': 2}
[1, 2, 3, 4, 5]
$ python3.14 -c "print([*L for L in [[1],[2]]])"
File "<string>", line 1
print([*L for L in [[1],[2]]])
^^
SyntaxError: iterable unpacking cannot be used in comprehension
[*L for L in lists] は [x for L in lists for x in L] と同じ意味で、二重ループの順番を考えずに平らにできます。 辞書は後ろの値が勝つので、'a' は 3 になります。リスト・集合・辞書・ジェネレーター式(async も含む)で使えます。
そのほかの言語の変更として、match のリテラルに単項の + が書けるようになり、slice が型引数を取れるようになり(slice[int])、bytes.replace() の count がキーワードで渡せるようになりました。
UTF-8がデフォルトになった影響(PEP 686)
この節では、3.15 でいちばん影響の大きい「encoding の既定が UTF-8 になった」変更で、何の結果が変わるかを実測で確かめられます。
3.15 では、open() などで encoding を省いたときの文字コードが、OS のロケールに関係なく UTF-8 になりました(UTF-8 モードが既定で有効)。 Linux や macOS の多くは元から UTF-8 なので差が出にくく、Windows(日本語版の既定は cp932)や、ロケールが UTF-8 でないサーバーで差が出ます。
Linux で差を見るため、作業場所に EUC-JP のロケール(ja_JP.eucJP)を作り、同じスクリプトを 3.14 と 3.15 で動かしました。eucjp.csv は EUC-JP で保存した CSV です。
import sys, locale
print(sys.version.split()[0], "utf8_mode=", sys.flags.utf8_mode,
"preferred=", locale.getpreferredencoding(False), "locale-enc=", locale.getencoding())
open("out.txt", "w").write("日本語")
print("write default ->", open("out.txt", "rb").read())
try:
print("read eucjp.csv default ->", open("eucjp.csv").readline().strip())
except UnicodeDecodeError as e:
print("UnicodeDecodeError:", e)
print("encoding='locale' ->", open("eucjp.csv", encoding="locale").readline().strip())
$ LC_ALL=ja_JP.eucJP python3.14 f_utf8b.py
3.14.10 utf8_mode= 0 preferred= EUC-JP locale-enc= EUC-JP
write default -> b'\xc6\xfc\xcb\xdc\xb8\xec'
read eucjp.csv default -> 社員名,部署
encoding='locale' -> 社員名,部署
$ LC_ALL=ja_JP.eucJP python3.15 f_utf8b.py
3.15.0 utf8_mode= 1 preferred= utf-8 locale-enc= EUC-JP
write default -> b'\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e'
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc in position 0: invalid start byte
encoding='locale' -> 社員名,部署
$ LC_ALL=ja_JP.eucJP PYTHONUTF8=0 python3.15 f_utf8b.py
3.15.0 utf8_mode= 0 preferred= EUC-JP locale-enc= EUC-JP
write default -> b'\xc6\xfc\xcb\xdc\xb8\xec'
read eucjp.csv default -> 社員名,部署
encoding='locale' -> 社員名,部署
同じ open("out.txt", "w") でも、3.14 は EUC-JP のバイト、3.15 は UTF-8 のバイトを書きました。 読む側も同じで、ロケールの文字コードで保存されたファイルを encoding なしで読むと、3.15 では UnicodeDecodeError になります。Windows に置き換えると、「cp932 で保存された CSV を open(path) で読んでいたコード」が 3.15 で止まる形です。
subprocess と標準出力も変わる
$ LC_ALL=ja_JP.eucJP python3.14 -c '...subprocess.run(["printf", EUC-JPの「日本」], text=True)...'
3.14.10 euc_jp euc_jp '日本'
$ LC_ALL=ja_JP.eucJP python3.15 -c '...同じ...'
3.15.0 utf-8 utf-8 '����'
左から sys.stdout.encoding・sys.getfilesystemencoding()・subprocess.run(..., text=True) で受け取った文字列です。ロケールの文字コードで出力する外部コマンドを text=True で受け取ると、3.15 では文字化け(置換文字)や例外になります。 外部コマンドの出力は encoding= を明記して受け取ります。
影響を洗い出す・元に戻す
| やりたいこと | 方法 | 確かめた結果 |
|---|---|---|
| encoding 無しの箇所を探す | python -X warn_default_encoding(3.10 から) |
3.14・3.15 とも EncodingWarning: 'encoding' argument not specified |
| ロケールの文字コードで読む | open(path, encoding="locale") |
3.15 でも EUC-JP のまま読めた |
| 当面だけ前の動きに戻す | PYTHONUTF8=0 か -X utf8=0 |
utf8_mode=0 になり 3.14 と同じ結果 |
| どの版でも同じ結果にする | encoding="utf-8" などを毎回書く |
公式もこれを最も確実な方法としている |
Windows での文字コードのエラー(cp932 で書けない文字)の直し方は、関連記事「UnicodeEncodeError: 'cp932'の直し方|Python」で扱っています。3.15 ではこのエラーの出方自体が変わる(既定が UTF-8 になる)ため、encoding を明記しているかどうかで結果が分かれます。
エラーメッセージの改善(3.14との比較)
この節では、3.15 でエラーメッセージに出るようになったヒントを、3.14 と並べて確かめられます。
$ python3.14 f_err.py
[1, 2, 3].push(4) -> AttributeError: 'list' object has no attribute 'push'
'hello'.toUpperCase() -> AttributeError: 'str' object has no attribute 'toUpperCase'
{}.put('a', 1) -> AttributeError: 'dict' object has no attribute 'put'
(1, 2, 3).append(4) -> AttributeError: 'tuple' object has no attribute 'append'
Container().area -> AttributeError: 'Container' object has no attribute 'area'
a = A(); delattr(a, 'abcdf') -> AttributeError: 'A' object has no attribute 'abcdf'
$ python3.15 f_err.py
[1, 2, 3].push(4) -> AttributeError: 'list' object has no attribute 'push'. Did you mean '.append'?
'hello'.toUpperCase() -> AttributeError: 'str' object has no attribute 'toUpperCase'. Did you mean '.upper'?
{}.put('a', 1) -> AttributeError: 'dict' object has no attribute 'put'. Use d[k] = v.
(1, 2, 3).append(4) -> AttributeError: 'tuple' object has no attribute 'append'. Did you mean to use a 'list' object?
Container().area -> AttributeError: 'Container' object has no attribute 'area'. Did you mean '.inner.area' instead of '.area'?
a = A(); delattr(a, 'abcdf') -> AttributeError: 'A' object has no attribute 'abcdf'. Did you mean '.abcde' instead of '.abcdf'?
JavaScript や Java の書き方(push・toUpperCase・put)をそのまま書いたときに、Python での正しい名前を教えてくれます。 Container().area では、属性 inner の中に area があることまで見つけています。ヒントはトレースバックを表示するときに付くので、str(e) には含まれません(上の出力は traceback.format_exception_only() で取り出しています)。
argparse も、suggest_on_error が既定で有効になりました。
$ python3.14 tool.py tset
tool: error: argument cmd: invalid choice: 'tset' (choose from 'build', 'test')
$ python3.15 tool.py tset
tool: error: argument cmd: invalid choice: 'tset', maybe you meant 'test'? (choose from 'build', 'test')
標準ライブラリの変更点(math.integer・re.prefixmatch・tomllib 1.1ほか)
この節では、標準ライブラリの追加・変更のうち、よく使いそうなものを実行結果つきで一覧できます。
$ python3.15 f_std.py; python3.15 f_async.py
math.integer: ['comb', 'factorial', 'gcd', 'isqrt', 'lcm', 'perm']
isqrt 10000000000 comb 120
prefixmatch: <re.Match object; span=(0, 3), match='123'> None
unicodedata 17.0.0
len 8
graphemes ['👨\u200d👩\u200d👧', '🇯🇵', 'が']
block Hiragana | CJK Unified Ideographs
toml: {'tbl': {'key': 'a string', 'n': 1}, 'dt': datetime.datetime(2026, 10, 9, 14, 15), 'esc': 'a\x1b['}
Counter ^: Counter({'a': 2, 'c': 2, 'b': 1})
take_bytes: b'hello' bytearray(b' world')
urlsafe no pad: b'abcd'
abi_info: namespace(pointer_bits=64, free_threaded=False, debug=False, byteorder='little')
crc32_combine: True
TaskGroup.cancel -> ['fast']
serialize_iterator -> [0, 1, 2, 3, 4]
| モジュール | 追加・変更 | 使いどころ |
|---|---|---|
| math.integer(新) | 整数の関数(comb・factorial・gcd・isqrt・lcm・perm)をまとめたサブモジュール(PEP 791) | math の同名関数は残っている |
| re | re.prefixmatch() を追加。re.match() はソフト非推奨(削除予定なし) |
「先頭から一致」を名前で明示 |
| unicodedata | Unicode 17.0.0。iter_graphemes()・block() など |
絵文字や国旗を「見た目の1文字」で数える |
| tomllib | TOML 1.1.0:インラインテーブルの改行と末尾カンマ、\xHH・\e、秒を省いた日時 |
上の出力の tbl・dt・esc |
| collections | Counter の ^(対称差) |
2つの集計の差分 |
| bytearray | take_bytes(n):コピーせずに先頭を bytes で取り出す |
受信バッファーの切り出し |
| asyncio | TaskGroup.cancel() |
残りのタスクをまとめて止める |
| threading | serialize_iterator・synchronized_iterator・concurrent_tee |
複数スレッドから1つのジェネレーターを読む |
| base64 | urlsafe_b64decode でパディング不要に。2〜3倍速く | JWT などの「=」を省いた値 |
| json | array_hook |
frozendict と組み合わせて変更できない設定 |
| pprint | expand=True(json.dumps の indent に近い形) |
入れ子の辞書を読みやすく表示 |
| sys・zlib・os | sys.abi_info、zlib.crc32_combine()、Linux の os.statx() |
環境の判定、分割データの検査 |
このほか、python --help・timeit・sqlite3・http.server などのコマンドラインの出力に色が付くようになりました。色が邪魔なときは PYTHON_COLORS=0 か NO_COLOR=1 で止められます。
Tachyon(profiling.sampling)で動いているプロセスを測る
この節では、3.15 で加わったサンプリングプロファイラー Tachyon で、スクリプトと動いているプロセスを測る手順と出力が分かります。
新しい profiling パッケージ(PEP 799)に、決定的なトレース(profiling.tracing、cProfile と同じもの)と、サンプリング方式の profiling.sampling(Tachyon)が入りました。 Tachyon はコードを変えずに、動いているプロセスへ後から付けられます。profile モジュールは非推奨になり、3.17 で削除されます。
$ python3.15 -m profiling.sampling run -r 1khz -l 8 slow.py
Captured 2043 samples in 2.04 seconds
Sample rate: 1000.00 samples/sec
Error rate: 4.01
Profile Stats:
nsamples sample% tottime (s) cumul% cumtime (s) filename:lineno(function)
1169/1169 59.6 1.169 59.6 1.169 slow.py:2(parse)
645/645 32.9 0.645 32.9 0.645 slow.py:3(compute.<locals>.<genexpr>)
98/1961 5.0 0.098 100.0 1.961 slow.py:7(main)
49/694 2.5 0.049 35.4 0.694 slow.py:3(compute)
次は、ループし続けるサーバー役のスクリプトを別に起動し、その PID に付けた例です。dump はその瞬間のスタック、attach -d 2 は2秒間のサンプリングです。
$ python3.15 -m profiling.sampling dump 14636
Stack dump for PID 14636, thread 14636 (main thread, has GIL, on CPU; most recent call last):
File "srv.py", line 6, in <module>
serve()
File "srv.py", line 5, in serve
handle(); time.sleep(0.001)
File "srv.py", line 2, in handle
def handle(): return sum(i*i for i in range(50_000))
$ python3.15 -m profiling.sampling attach -d 2 -l 5 --no-summary 14636
Captured 2000 samples in 2.00 seconds
Sample rate: 999.99 samples/sec
Error rate: 15.30
nsamples sample% tottime (ms) cumul% cumtime (s) filename:lineno(function)
684/1694 40.4 684.000 100.0 1.694 srv.py:5(serve)
602/602 35.5 602.000 35.5 0.602 srv.py:2(handle.<locals>.<genexpr>)
408/1010 24.1 408.000 59.6 1.010 srv.py:2(handle)
止まっている・遅いプロセスを再起動せずに、どの行にいるかを確かめられるのが大きな違いです。 出力は --flamegraph(HTML)・--collapsed・--pstats・--gecko(Firefox Profiler)・--heatmap から選べ、--mode で wall・cpu・gil・exception を切り替えられます。公式ドキュメントによると、ほかのプロセスに付けるには、Linux では root・CAP_SYS_PTRACE・Yama の ptrace_scope のいずれか、macOS では root など、Windows では管理者権限か SeDebugPrivilege が要ります。この環境は root で動かしたため付けられました。測る側と測られる側は同じマイナー版(どちらも 3.15)である必要があり、フリースレッド版と通常版の間でも付けられません。
JITとフリースレッドの速さを実測(3.14との比較)
この節では、Python 3.15 の JIT とフリースレッド版で、手元の処理がどれだけ速くなるかの実測が分かります。
公式の What's New では、JIT は x86-64 Linux の pyperformance で通常のインタープリターより 7〜8%(幾何平均)、AArch64 macOS で 11〜12% 速いと公表されています。 処理によっては約15%遅くなるものから2倍以上速くなるものまで幅がある、とも書かれています。JIT は今も実験的な機能で、PYTHON_JIT=1 で有効にします。
$ python3.15 -c 'import sys; print(sys._jit.is_available(), sys._jit.is_enabled())'
True False
$ PYTHON_JIT=1 python3.15 -c 'import sys; print(sys._jit.is_available(), sys._jit.is_enabled())'
True True
小さなベンチマーク5つを、3.14.10 と 3.15.0 で JIT の有無を変えて測りました。各処理を7回動かした CPU 時間の最小値を1回分とし、4つの組み合わせを交互に3巡した中央値です(同じマシンで他の処理も動いているため、数%の差は誤差の範囲です)。
| 処理 | 3.14 JIT無 | 3.14 JIT有 | 3.15 JIT無 | 3.15 JIT有 |
|---|---|---|---|---|
| 再帰 fib(30) | 77ms | 77ms | 78ms | 67ms(−14%) |
| float の足し算 300万回 | 142ms | 152ms | 143ms | 112ms(−22%) |
| 小さなオブジェクト生成 200万個 | 224ms | 229ms | 238ms | 254ms(+7%) |
| n体問題 15万ステップ | 224ms | 312ms | 216ms | 192ms(−11%) |
| ジェネレーター式 300万件 | 134ms | 133ms | 151ms | 140ms(−7%) |
( )内は 3.15 の JIT 無しとの差です。3.15 の JIT は5つ中4つで短くなり、3.14 の JIT で遅くなっていた n体問題(224→312ms)も 192ms まで縮みました。 一方、オブジェクト生成は 3.15 の JIT 有りがいちばん遅く、JIT 無しどうしでは 3.15 が 3.14 よりやや遅い処理もありました。公式の数字どおり、処理によって結果が分かれるので、自分のコードで測ってから使うかを決めるのが確実です。
base64 は大きく速くなった
| 処理(CPU 時間の最小値) | 3.14.10 | 3.15.0 |
|---|---|---|
| b64encode 8MB | 18.6ms | 4.3ms |
| b64decode 8MB | 9.5ms | 5.3ms |
| b85encode 200KB | 11.7ms | 0.3ms |
| b32encode 200KB | 14.5ms | 0.1ms |
公式には「base64 のエンコードが2倍、デコードが3倍速い」「Base85・Base32 は C で書き直されて2桁速い」とあり、手元でも同じ傾向でした。
フリースレッド版(3.15t)でスレッドが並列に動くか
$ uv python install 3.15.0t
+ cpython-3.15.0+freethreaded-linux-x86_64-gnu (python3.15t)
$ python3.15t -VV
Python 3.15.0 free-threading build (main, Oct 14 2026, 01:06:54) [Clang 23.1.3 ]
$ python3.15 ft.py
3.15.0 gil=True 1thread 121ms 2threads 127ms speedup 0.95x
$ python3.15t ft.py
3.15.0 gil=False 1thread 139ms 2threads 68ms speedup 2.04x
CPU だけを使う計算を、1スレッドと2スレッドに分けて比べました(2回目は 1.73 倍)。通常版では2スレッドにしても速くならず、フリースレッド版では2コアでほぼ2倍になりました。 その代わり1スレッドでは通常版より約15%遅く、C 拡張がフリースレッドに対応しているかも確かめる必要があります。3.15 では C 拡張がフリースレッド版向けの安定 ABI(abi3t、PEP 803)を使えるようになり、対応が進めやすくなりました。プロセスとスレッドの使い分けは、関連記事「Python並列処理|concurrent.futures使い分けと速度比較」で扱っています。
Python 3.14から移行すると壊れる点(削除・非推奨の一覧)
この節では、3.14 では警告だけだったのに 3.15 でエラーになる API を、両方の版の出力で確かめられます。
同じスクリプトで14項目を試しました。3.14 で DeprecationWarning が出ていたものは、3.15 でほぼすべてエラーになります。 警告を表示しない設定で動かしていると、3.15 で初めて気づくことになります。
| コード | 3.14.10 | 3.15.0 | 置き換え |
|---|---|---|---|
import sre_compile |
DeprecationWarning | ModuleNotFoundError | re を使う |
strptime('02-29', '%m-%d') |
ValueError(day 29 must be in range)+警告 | ValueError(%d を年なしで使えない) | 年を入力と書式に足す |
NamedTuple('P', x=int) |
DeprecationWarning | TypeError | class 構文か [("x", int)] |
TypedDict('TD') |
DeprecationWarning | TypeError | TypedDict('TD', {}) |
ast.Name()(引数不足) |
DeprecationWarning | TypeError | 必須の引数を渡す |
glob.glob0() |
DeprecationWarning | AttributeError | glob.glob(root_dir=...) |
platform.java_ver() |
DeprecationWarning | AttributeError | なし(削除) |
code.co_lnotab |
DeprecationWarning | AttributeError | co_lines() |
CGIHTTPRequestHandler |
そのまま動く | ImportError | WSGI など別の仕組み |
PurePath.is_reserved() |
DeprecationWarning | AttributeError | os.path.isreserved() |
sqlite3.connect(db, 5.0) |
DeprecationWarning | TypeError | timeout=5.0 とキーワードで |
from collections.abc import ByteString |
警告なし | DeprecationWarning(3.17 で削除) | collections.abc.Buffer など |
hashlib.sha256(string=b'x') |
警告なし | DeprecationWarning(3.19 で削除) | 位置引数か data= |
module.__cached__ |
.pyc のパスが入る | 設定されない | __spec__.cached |
3.15 で実際に出たエラーの原文です。原因を探すときは、この文字列で検索するのが早道です。
[sre_compile] ModuleNotFoundError: No module named 'sre_compile'. Did you mean: 'py_compile'?
[strptime %d] ValueError: Day of month directive '%d' may not be used without a year directive. Parsing dates involving a day of month without a year is ambiguous and fails to parse leap day. Add a year to the input and format. See https://github.com/python/cpython/issues/70647.
[NamedTuple kw] TypeError: NamedTuple() got an unexpected keyword argument 'x'
[TypedDict 0 field] TypeError: TypedDict() missing 1 required positional argument: 'fields'
[ast node] TypeError: ast.Name.__init__ missing 1 required positional argument: 'id'
[glob0] AttributeError: module 'glob' has no attribute 'glob0'. Did you mean '.glob' instead of '.glob0'?
[platform.java_ver] AttributeError: module 'platform' has no attribute 'java_ver'. Did you mean '.mac_ver' instead of '.java_ver'?
[co_lnotab] AttributeError: 'code' object has no attribute 'co_lnotab'. Did you mean '.co_linetable' instead of '.co_lnotab'?
[CGIHTTPRequestHandler] ImportError: cannot import name 'CGIHTTPRequestHandler' from 'http.server'
[PurePath.is_reserved] AttributeError: 'PurePosixPath' object has no attribute 'is_reserved'
[sqlite3 positional] TypeError: connect() takes at most 1 positional arguments (2 given)
このほか、公式の「Porting to Python 3.15」には次の変更が挙がっています。
- argparse:
add_argument('-f', '-foo')の dest がfからfooに変わった(手元でも 3.14 はNamespace(f='1')、3.15 はNamespace(foo='1')) - base64:
urlsafe_b64decodeがパディングを求めなくなった。必須にするならpadded=True - unittest:
assertWarnsが一致しない警告を飲み込まなくなり、隠れていた警告が出てくることがある - xml.etree:ファイルを開いた
iterparseを閉じないと ResourceWarning - gc:3.14.0〜3.14.4 の増分 GC は戻され、3.14.5 以降と 3.15 は世代別 GC
- .pth の import 行:新しい
.startファイル(PEP 829)への移行が始まり、対応する .start があると無視される - ビルド:フレームポインターが既定で有効(PEP 831)。独自のビルドで C 拡張を作る場合はフラグを揃える
上げる前に確かめたいことをまとめると、次の5つです。
- 1依存パッケージに cp315 の wheel があるかuv pip install --python 3.15 -r requirements.txt で試す
- 23.14 で DeprecationWarning を表示して消したかpython -W error::DeprecationWarning でテストを流す
- 3encoding 無しの open・subprocess を洗い出したか-X warn_default_encoding で見つかる
- 4CI に 3.15 を足したか3.14 と並べて同じテストを流す
- 5使う版は 3.15.2 以降か3.15.0 の import の退行が直っている
よくあるエラー/つまずき(Python 3.15)
この節では、3.15 を入れたときに出やすいエラーを、原文・原因・直し方の順に引けます。
| エラー・症状(原文) | 原因 | 直し方 |
|---|---|---|
error: No download found for request: cpython-3.15.0-linux-x86_64-gnu |
uv が 3.15.0 より前の版 | uv を更新する |
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc |
ロケールの文字コードのファイルを encoding 無しで読んだ | encoding="cp932" などを書く |
SyntaxError: lazy import not allowed inside functions |
関数の中で lazy | モジュールの一番外に書く |
SyntaxError: invalid syntax(lazy の行) |
3.14 以前で動かした | __lazy_modules__ を使う |
NameError: name 'frozendict' is not defined. Did you mean: 'frozenset'? |
3.14 以前で動かした | 3.15 で動かすか、版で分岐する |
TypeError: connect() takes at most 1 positional arguments (2 given) |
sqlite3.connect の引数がキーワード専用に | timeout= などキーワードで渡す |
| pip install で C のビルドが始まり失敗する | そのパッケージに cp315 の wheel が無い | 対応版を待つか 3.14 に留まる |
~/.local/bin に python3.15 が増えた |
uv python install の既定の動き | UV_PYTHON_BIN_DIR か --no-bin で場所を変える |
Python 3.15に上げるかの判断表
この節では、状況ごとに 3.15 に上げるか待つかを1行で選べます。
| 状況 | 判断 | 理由 |
|---|---|---|
| 新しく作るプロジェクト | 3.15.2 で始める | 主要ライブラリの wheel があり、サポートが最も長い |
| Windows で日本語のファイルを扱う既存の業務システム | encoding を明記してから上げる | cp932 の読み書きの結果が変わる |
| C 拡張に頼る(独自ビルド・更新の止まったライブラリ) | wheel が揃うまで 3.14 | 手元でビルドが要る |
| 起動の速さが大事な CLI・サーバーレス | 3.15 で lazy を試す | 実測で起動が 97ms→13ms |
| CPU を使う計算をスレッドで並列にしたい | 3.15t を検証 | 2スレッドで約2倍。1スレッドは約15%遅い |
| 3.13 以前を使っている | 3.14 を経由して警告を消す | 3.14 の警告がそのまま 3.15 の削除一覧 |
| JIT で速くしたい | 自分の処理で測ってから | 実験的機能。手元では遅くなる処理もあった |
よくある質問(Python 3.15)
この節では、Python 3.15 についてよく聞かれることに短く答えます。
Q. Python 3.15 のリリース日はいつですか? A. 3.15.0 が 2026年10月9日です。最初のアルファ版は2025年10月14日、ベータ1は2026年5月7日でした。3.15.1 が10月21日、3.15.2 が10月26日に出ています(PEP 790)。
Q. Python 3.15 の新機能を一言でいうと? A. 書き方では lazy import・frozendict・sentinel・内包表記のアンパック、動きでは UTF-8 のデフォルト化、道具では Tachyon プロファイラーと JIT の強化です。
Q. Python 3.14 との違いでいちばん注意する点は?
A. encoding を省いた入出力が UTF-8 になった点です。Windows で cp932 のファイルを open(path) で読んでいたコードは UnicodeDecodeError になります。次が、3.14 で非推奨だった API の削除です。
Q. lazy import を使うと必ず速くなりますか? A. 使わないモジュールの読み込みが減る分だけ起動が速くなります。今回の CLI では 97.0ms が 12.7ms になりましたが、全部のモジュールを毎回使う処理では差は出ません。読み込みの失敗が使った行まで遅れる点にも注意します。
Q. frozendict と MappingProxyType の違いは? A. MappingProxyType は元の辞書を読み取り専用で見せる窓で、元を変えると見え方も変わり、ハッシュもできません。frozendict はそれ自体が変更できない値で、ハッシュ可能なので辞書のキーにできます。
Q. Python 3.15 は uv で入れられますか?
A. 入れられます。ただし 3.15.0 が出る前に配布された uv は 3.15.0 を知らないため、uv を更新してから uv python install 3.15 を実行します。手元の uv 0.11.32 はベータ4まで、0.13.7 は 3.15.2 まで表示しました。
Q. GIL は無くなったのですか? A. 通常版には GIL があります。GIL の無いフリースレッド版(3.15t)は別のビルドとして配布され、macOS の公式インストーラーでは既定で一緒に入ります。手元では2スレッドで約2倍速くなりました。
Q. JIT はどうすれば有効になりますか?
A. JIT 付きでビルドされた Python で、環境変数 PYTHON_JIT=1 を付けて起動します。sys._jit.is_enabled() で確かめられます。実験的な機能で、処理によっては遅くなります。
Q. re.match は使えなくなりますか?
A. 使えます。ソフト非推奨になっただけで、公式は削除しないと明言しています。新しく書くコードは re.prefixmatch() が推奨で、以前の版にも対応させるコードは re.match() のままにします。
Q. Python 3.15 はいつまでサポートされますか? A. バグ修正はおよそ2年間(3.17.0 のころまで)、セキュリティ修正は2031年10月ごろまでです。
まとめ
- Python 3.15.0 は 2026年10月9日に公開。 使うなら退行の直った 3.15.2 以降を選ぶ
- 新しい書き方は lazy import・frozendict・sentinel・内包表記の * と **。 lazy で CLI の起動が 97ms から 13ms になった
- いちばん影響が大きいのは UTF-8 のデフォルト化。 encoding を省いた open・subprocess の結果が、ロケールが UTF-8 でない環境で変わる
- 3.14 で警告だった API は 3.15 でエラーになる。 3.14 のうちに DeprecationWarning を消しておくと移行が楽になる
- uv で入れるときは uv を先に更新する。 以前の uv は 3.15.0 を知らず、
~/.local/binへのリンクも作る
参考・出典
確認日はいずれも 2026年11月5日です。
- Python 公式ドキュメント「What's New In Python 3.15」:https://docs.python.org/3.15/whatsnew/3.15.html
- CPython リポジトリ「Doc/whatsnew/3.15.rst」(3.15 ブランチ):https://github.com/python/cpython/blob/3.15/Doc/whatsnew/3.15.rst
- python.org「Python 3.15.0」リリースページ:https://www.python.org/downloads/release/python-3150/
- PEP 790「Python 3.15 Release Schedule」:https://peps.python.org/pep-0790/
- PEP 810「Explicit lazy imports」:https://peps.python.org/pep-0810/
- PEP 814「Add frozendict built-in type」:https://peps.python.org/pep-0814/
- PEP 661「Sentinel Values」:https://peps.python.org/pep-0661/
- PEP 798「Unpacking in Comprehensions」:https://peps.python.org/pep-0798/
- PEP 686「Make UTF-8 mode default」:https://peps.python.org/pep-0686/
- PEP 799「A dedicated profiling package」:https://peps.python.org/pep-0799/
- PEP 803「Stable ABI for free-threaded builds」:https://peps.python.org/pep-0803/
- Python 公式ドキュメント「profiling.sampling --- Statistical profiler」:https://docs.python.org/3.15/library/profiling.sampling.html
- Python 公式ドキュメント「Using Python on Windows」:https://docs.python.org/3.15/using/windows.html
- uv 公式ドキュメント「Python versions」:https://docs.astral.sh/uv/concepts/python-versions/
- uv(PyPI):https://pypi.org/project/uv/
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Python 3.15の新機能と変更点|3.15.0を入れて3.14と実測比較」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。