結論

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項目のエラー原文と直し方

2026年11月5日更新|Python 3.15.0・3.14.10(uv 0.13.7)で実行確認

この記事で実際に動かしたもの: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 を見つけられないときの原因が分かります。

1

uv を新しくする

uv は配布される Python の一覧を本体に持っている。3.15.0 が出る前の uv は 3.15.0 を知らない。

uv self update / pip install -U uv

2

版を指定して入れる

uv python install 3.15 で最新のパッチ版、3.15.0 なら版を固定。フリースレッド版は 3.15t。

uv python install

3

版を確かめる

python3.15 -VV でビルド日とコンパイラーまで出る。

python -VV

4

プロジェクトで使う

uv init --python 3.15 か uv python pin 3.15。.python-version に書かれる。

uv init / uv python pin

以前の 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回ずつ起動した中央値です。

97.0ms通常の import3.15.0。3.14.10 は 107.8ms
12.7mslazy importpython -c pass と同じ
23.3mslazy で json だけ使う使った分だけ読み込む
起動のしかた(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' になります。

型の判定で起きる違い

isinstance(x, dict)frozendict は dict の子クラスではないので False。dict だけを受け付ける関数は frozendict をはじく
→
isinstance(x, Mapping)collections.abc.Mapping なら True。読むだけの関数はこちらで判定する

公式の 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期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

成長のヒミツ、 ぜんぶ丸わかり