Python 3.13の変更点 - Free-threaded CPythonと実験的JITの注意点

8分 で読める | 2025.12.08

公式ドキュメント

Python 3.13は2024年10月7日にreleaseされた安定版です。通常のPython 3.13自体はstableですが、話題になったGIL無効化buildとJIT compilerは3.13時点で実験的機能です。この区別をせず、「Python 3.13ではGILがなくなった」「JITで自動的に高速化する」と理解するのは正しくありません。

主要変更の状態

記事情報: 2025年12月8日初出。Python 3.13公式資料を2026年7月25日に再確認しています。

Python 3.13の主な変更を状態別に整理すると次のようになります。

機能3.13での状態
新しいinteractive interpreter通常buildで利用可能
tracebackのcolor表示通常buildで既定有効
locals()の定義明確化language仕様として反映
type parameterのdefault利用可能
free-threaded CPython実験的・別build
JIT compiler実験的・既定無効

production更新では、まず通常buildのPython 3.13へ移行し、free-threaded buildやJITの検証は別に行うと問題を切り分けやすくなります。

Free-threaded CPythonとは

通常のCPythonにはGIL(Global Interpreter Lock)があり、1つのinterpreter process内では、基本的に同時に1つのthreadがPython bytecodeを実行します。I/O待ちが多い処理ではthreadを有効に使えますが、Python code中心のCPU-bound処理は複数coreへそのまま広がりません。

Python 3.13ではPEP 703に基づき、GILを無効化できるfree-threaded buildが実験的に提供されました。通常buildへflagを1つ付けるだけではなく、一般にpython3.13tまたはpython3.13t.exeという別の実行ファイルを使います。WindowsとmacOSの公式installerではoptional componentとして導入でき、sourceからは--disable-gilでbuildします。

実行中の状態を確認する

import sys

print(sys.version)
print("GIL enabled:", sys._is_gil_enabled())

python -VVまたはsys.versionには、対象がexperimental free-threading buildであることが表示されます。sys._is_gil_enabled()を使えば、そのprocessで実際にGILが有効か確認できます。

free-threaded buildでも、次のようにGILを有効にして実行できます。

python3.13t -X gil=1 app.py

反対に-X gil=0で明示的に無効化できますが、利用libraryが対応していることを確認せず強制しないでください。

free-threaded modeの制約

公式What’s Newは、3.13のfree-threaded modeにはbugの可能性があり、single-thread性能に大きな低下があり得ると注意しています。threadを使えばどのprogramも速くなるわけではありません。

特に重要なのがC extensionです。extension moduleはfree-threaded build向けにbuildされ、GIL無効化対応を明示する必要があります。対応を示さないC extensionをimportすると、明示的にGIL無効化を強制していない限りGILが有効になります。

また、GILがなくてもdata raceがなくなるわけではありません。複数threadが同じapplication stateを更新する場合は、lock、queue、不変dataなどで同期します。

from concurrent.futures import ThreadPoolExecutor
from threading import Lock

total = 0
total_lock = Lock()


def add(value: int) -> None:
    global total
    with total_lock:
        total += value


with ThreadPoolExecutor(max_workers=4) as executor:
    list(executor.map(add, range(1000)))

print(total)

この例はparallel性能を示すbenchmarkではなく、共有stateには同期が必要だと示すものです。性能評価では実際の処理を使い、通常build、free-threaded build、multiprocessingなどを同じ条件で比較します。

実験的JIT compiler

Python 3.13にはPEP 744の基本的なJIT compilerが入りましたが、通常配布のPythonで自動的に有効になる機能ではありません。CPythonを--enable-experimental-jit付きでbuildする必要があり、既定では無効です。

JITは頻繁に実行されるbytecodeを内部のTier 2 IRへ変換し、最適化後にmachine codeとして実行する仕組みです。ただし3.13の公式資料は、性能改善はmodestであり、今後のreleaseで改善する予定だと説明しています。

したがって、3.13へupgradeする理由をJITだけに置くべきではありません。JITを検証する場合は、対応platformとbuild toolchainをそろえ、対象applicationで起動時間、throughput、memory、tail latencyを測ります。JIT build自体が通常buildと異なることも記録してください。

新しいinteractive interpreter

interactive terminalでpythonを起動すると、新しいREPLが既定で使われます。PyPy projectのcodeを基にし、次の操作が追加されました。

  • 複数行編集とhistory保持
  • helpexitquitを括弧なしで実行
  • promptとtracebackのcolor表示
  • F1でhelp、F2でhistory、F3でpaste mode
$ python3.13
Python 3.13...
>>> values = [
...     1,
...     2,
...     3,
... ]
>>> sum(values)
6

CI、redirectされたstandard input、一部terminalでは表示や操作が異なります。問題がある場合はPYTHON_BASIC_REPL環境変数で従来型のbasic REPLへ戻せます。colorはPYTHON_COLORSなどで調整できます。

locals()の仕様が明確になった

PEP 667により、locals()が返すmappingの挙動が定義されました。function、generator、coroutine、comprehensionなどのoptimized scopeでは、locals()はその時点の独立したsnapshotを返します。

def example() -> int:
    value = 1
    snapshot = locals()
    snapshot["value"] = 99
    return value


print(example())  # 1

debuggerやexec()eval()など、local variableを書き換える前提のtoolに影響する可能性があります。通常のbusiness codeでlocals()を更新して状態を変更する設計は避け、明示的なdictionaryを使うほうが分かりやすくなります。

typingと標準library

PEP 696により、TypeVarParamSpecTypeVarTupleなどのtype parameterにdefaultを指定できます。またPEP 702のwarnings.deprecated()により、runtime warningとtype checkerの両方へdeprecationを表現できます。

from typing import TypeVar

T = TypeVar("T", default=str)

type checkerごとに対応時期が異なるため、Python interpreterを更新しただけでeditorやCIが同じ解釈になるとは限りません。mypy、Pyrightなど実際に使うtoolの対応versionも確認します。

一方、PEP 594により、aifcaudioopcgicgitbchunkなど、以前からdeprecatedだった複数の標準moduleが削除されました。直接importしていなくても依存libraryが利用している場合があります。

python3.13 -m pip install -r requirements.txt
python3.13 -m pytest

install成功だけで移行完了とせず、CLI、batch、web process、test、build scriptを一通り動かします。

3.12からの移行手順

  1. Python 3.13の通常buildで新しいvirtual environmentを作る
  2. pipとbuild toolを更新し、依存を入れ直す
  3. test、type check、lintを実行する
  4. 削除moduleとdeprecated APIを検索する
  5. C extensionを含むpackageのwheel対応を確認する
  6. stagingでmemory、CPU、response timeを測る
  7. free-threaded/JITは別環境・別評価として試す
python3.13 -m venv .venv313
source .venv313/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pytest

OSによってcommand名とvirtual environmentの有効化方法は異なります。production imageではminor versionまで固定し、local・CI・本番の差を減らしてください。

まとめ

Python 3.13は、新しいREPL、error表示、typing、標準libraryなど通常利用できる改善を含むstable releaseです。一方、free-threaded CPythonとJITは将来の方向を試す実験的機能であり、production-readyと同一視できません。

通常buildへのupgradeと実験機能の評価を分け、依存package、C extension、thread safety、実測性能を確認してください。特にfree-threaded modeは「GILを無効にできる」ことと「既存codeが安全かつ高速に動く」ことを分けて判断する必要があります。

参考リソース

← 一覧に戻る
PR
PR
PR
PR