What’s New In Python 3.14 ノート

What’s New In Python 3.14 をたどりながら調査。興味のあるものしか読まない。

New features

PEP 750: Template string literals

A template string literal or t-string is a string literal that is prefixed
with ‘t’ or ‘T’. These strings follow the same syntax rules as formatted
string literals. (2.5.8 t-strings)

定義方法や書式・変換指定は従来の f-string と同様だが、この形式で定義した文字列は実は文字列ではなく string.templatelib.TemplateString オブジェクトになる。

Templates provide developers with access to the string and its interpolated
values before they are combined. This brings native flexible string processing
to the Python language and enables safety checks, web templating,
domain-specific languages, and more. (PEP 750)

コードを見るほうが理解が早い:

t-string の基本性質を簡単に示すコード片
name = "World"
t = t"Hello {name}"

assert t.strings[0] == "Hello "
assert t.interpolations[0].value == "World"
assert t.interpolations[0].expression == "name"

contents = list(t)
assert len(contents) == 2
assert contents[0] == "Hello "
assert contents[1].value == "World"
assert contents[1].expression == "name"

ここまで試して気付いたが、オブジェクトの最終形を普通の文字列として一発で出力する方法が用意されていない。それがこの新型クラスの狙いでもあるようだ。ユーザー入力を検証する処理と文字列を組み立てる処理が一体化したものをプログラマーが定義するのだ。

Improved error messages

インタプリターからの SyntaxError メッセージがわかりやすくなった。

  • インタプリターが Python キーワードに酷似した単語を検出すると、エラーメッセージ内で正しいキーワードを提案する。

  • else 節に続く elif 文に対しては専用のエラーメッセージが表示される。

  • 三項演算子の else 後の条件式に文が渡されたり、if の前に pass, break, continue のいずれかが渡されたりした場合、式が必要な箇所をエラーメッセージ中で強調表示する。

  • 不正に閉じられた文字列が検出された場合、エラーメッセージがその文字列が意図的に文字列の部分であるかもしれないことを示唆する。

  • 文字列の接頭辞が複数付いていてそれらに互換性がない場合のエラーメッセージ

  • 次のような as に関係するエラーメッセージ:

    • import ... as ...

    • from ... import ... as ...

    • except ... as ...

    • case ... as ...

  • ハッシュ化できない型のオブジェクトを dictset に追加しようとした際のエラーメッセージ

  • async with が適切な場所で with を指定した場合、またはその反対の指定を行った場合のエラーメッセージ

Asyncio introspection capabilities

モジュール asyncio に CLI が搭載された。コマンドは pspstree の二つある。どちらもプロセスを ID の値で指定して、実行中の asyncio タスクに関する情報を標準出力に示すものだ。

この機能は長時間実行される、または停止した非同期プログラムの調査に有用だ。

タスクの情報は次で構成される:

  • タスクの名前

  • タスクのコルーチンスタック

  • タスクを待機しているタスクの集合

コマンド pspstree はこの情報を表形式と、非同期呼び出し関係に関する木形式でそれぞれ出力する。

引数はプロセス ID 一個のみだ。オプションは -h, --help しかない。

Todo

可能ならば、長時間実行の非同期プログラムを走らせて、コマンド python -m asyncio pstree の実際の出力をここに記したい。

Other language changes

  • 複素数の値に対して inf と nan を複合させた演算結果が C++11 におけるそれと適合するようになった。

  • Python の最適化オプション -O 絡みの SyntaxError 検出精度が上がった。

Built-ins

  • メソッド fromhex() の機能向上。クラス bytesbytearray のこれらのメソッドは、引数として ASCII bytes 値(実質的には ASCII 文字列値)や bytes 風オブジェクトを受け容れる。

  • クラスメソッド from_number() の追加。クラス floatcomplex に対してこのメソッドが追加した。与える引数は実数でなければならない。コンストラクターのように扱いたい。

  • 文字列書式における浮動小数点表示形式の端数部分で、千の位区切り記号として _, を用いることが許される。例えば format(123456.123456, '_._f') がエラーでなくなった。

  • 関数 int()__trunc__() を呼び出さない。整数に変換したいクラスは次のいずれかを実装することが不可欠になった:

    • __int__()

    • __index__()

  • 関数 map() にキーワード専用引数 strict が追加。関数 zip() のそれと同じ仕様だ。

  • クラス memoryview が generic になった。つまり、型注釈を付けるときに何の型の器なのかを示せるようになった。

  • ブール値の文脈で NotImplemented を使用すると TypeError が発生するようになった。

    >>> if NotImplemented:
    ...     pass
    ...
    Traceback (most recent call last):
      File "<python-input-18>", line 1, in <module>
        if NotImplemented:
           ^^^^^^^^^^^^^^
    TypeError: NotImplemented should not be used in a boolean context
    
  • 三引数 pow() は必要に応じて __rpow__() を試みるようになった。

  • super オブジェクトはコピー可能かつ pickle 可能になった。

Command line and environment

コマンド python -c が実行前にコード引数のインデントを自動的に解除するようになった(コード文字列の各行から共通の先頭空白が取り除かれ、実行される)。

PEP 758: Allow except and except* expressions without brackets

except / except* 式のどちらにおいても、as 句が使用されていないような場合に、例外型を列挙するときに欠かせなかった囲む括弧が省略可能になった(もちろん囲んでもかまわない)。PEP 758 から例を引用する:

PEP 758 より
try:
    ...
except ExceptionA, ExceptionB, ExceptionC:
    ...

捕捉する例外に名前を付ける場合には括弧が必須であるのは変わらない理由は、試しに上のコードに括弧を加えぬままに as e を付けて、じっと眺めていればわかる。

PEP 765: Control flow in finally blocks

例外処理の finally 節が次の文を含むとき、それは SyntaxWarning を生じるようになった:

  • break

  • continue

  • return

というのは、そのようなコードを書いて実際にこのような制御文が実行される場合、例外が再送出されない、つまり、例外が失われるという言語仕様があるのだ。

PEP 765 を Python 3.14 で検証する例
>>> def test_control_flow_in_finally_block():
...     try:
...         raise ValueError
...     finally:
...         return 1
...     return 0
...
<python-input-0>:5: SyntaxWarning: 'return' in a 'finally' block
>>> test_control_flow_in_finally_block()
1

Default interactive shell

対話型シェルで Python 構文の強調表示がなされるようになった。オフにしたい場合には環境変数 PYTHON_BASIC_REPL を定義しろ。

Note

この環境変数を定義しなくても、Python はよそで用いられる次の環境変数を考慮して強調表示をやめる:

  • TERM

  • NO_COLOR

  • FORCE_COLOR

さらに対話型シェルは import 文における自動補完を応援するようになった。例:

  • import co までタイプして Tab を押すと、名前の先頭が co から始まるモジュール一覧が候補として示される。

  • from concurrent import i までタイプして Tab を押すと、標準モジュール concurrent のサブモジュールであって、名前の先頭が i で始まるものの一覧が候補として示される。

New modules

annotationlib

次の注釈用の道具を含むモジュール:

  • 関数 get_annotations()

  • 書式設定に用いる列挙型

  • クラス ForwardRef

  • 関数 __annotate__ を呼び出すための補助関数

compression

圧縮関連モジュール用のパッケージ。Zstandard 圧縮形式を使用することが可能になる新モジュールを含む。

次の既存&新圧縮アルゴリズム搭載標準モジュール群を含む:

  • bz2

  • gzip

  • lzma

  • zlib

  • compression.zstd

concurrent.interpreters

標準ライブラリーにあるインタプリター複数を使用することが可能となるモジュール。

string.templatelib

先述の t-strings を使用可能にするモジュール。

Improved modules

興味のあるものや遭遇しそうな問題を含むモジュールに絞って記していく。

argparse

Click を使う場合は流し読みでいい。

  • ArgParser のプログラム名の既定値を、インタプリターが __main__ モジュールコードを検索するように指示された方法に従って決まるようになった。つまり、コマンドラインで --help 出力で示されるプログラム名称のことだが、次のように決定する:

    • 引数としてファイルが渡された場合は basename sys.argv[0] 相当

    • 引数としてディレクトリーまたは zip ファイルが渡された場合は sys.argv[0]

    • python -m で起動された場合、モジュールまたはパッケージの名前

  • ユーザーによる誤入力時に引数選択肢などの候補表示が可能になった。それには ArgumentParser コンストラクターでオプション引数 suggest_on_error=True を指定する。オブジェクト生成してから parse() するまでの頃合いならば、オブジェクトの属性値を直接 True に代入することによっても、期待どおり動作する。

  • ヘルプテキストの色強調表示がなされるようになった。これを従来どおりのオフにするには ArgumentParser コンストラクターで color=False とすればいい。 先述の環境変数 を設定することでも切り替え可能だ。

asyncio

  • 関数とメソッドで三種存在する create_task() が任意のキーワード引数リストを受理するようになった。

    • キーワード引数はすべて Task または自作ファクトリーに転送される。

    • キーワード引数 name および context に対する特別扱いは失われた。

  • 関数 capture_call_graph()print_call_graph() が設けられた。呼び出し側が Task または Future オブジェクトを指定すると、その非同期呼び出しグラフオブジェクトが戻るか、当該グラフオブジェクトをファイルなどに出力する。

calendar

コマンド python -m calendar を実行したときに、今日が強調表示されるようになった。この挙動は環境変数 PYTHON_COLORS および 先述の環境変数 により変更することが可能だ。

configparser

  • 読み取り不能設定ファイルへの書き込みを行わなくなった。

  • 区切り文字を含むキーやセクションヘッダーパターンで始まるキーへの write() を試みると例外 InvalidWriteError が送出するようになった。

datetime

次のクラスにクラスメソッド strptime() が加わった:

  • datetime.date

  • datetime.time

An example of datetime.time.strptime()
>>> from datetime import import time
>>> time.strptime("2 時 50 分", "%H 時 %M 分")
datetime.time(2, 50)

decimal

クラスメソッド from_number() が加わった。戻り値の型を除けば、このメソッドは上述の floatcomplex のそれと同様に動作する。

算術演算環境として IEEEContext 型を新たに使用可能になった。

An example of using IEEEContext
>>> 1 / 7
0.14285714285714285
>>> from decimal import Decimal, IEEEContext, localcontext
>>> print(Decimal('1.0') / Decimal('7.0'))
0.1428571428571428571428571429
>>> decimal.IEEEContext(64)
Context(prec=16, rounding=ROUND_HALF_EVEN, Emin=-383, Emax=384, capitals=1, clamp=1, flags=[], traps=[])
>>> ctx = _
>>> with localcontext(ctx):
...     print(Decimal('1.0') / Decimal('7.0'))
...
0.1428571428571429

fractions

メソッド as_integer_ratio() を持つオブジェクトならば、何であってもそれから Fraction オブジェクトを生成可能になった。

クラス Fraction にクラスメソッド from_number() が加わった。意味は先述の同名メソッドと同様にはたらくが、引数は次のいずれかを満たす必要がある:

  • 値の型が numbers.Integral, numbers.Rational, float, decimal.Decimal のいずれかである。

  • オブジェクトがメソッド as_integer_ratio() を有する。

functools

関数 reduce() の最初の引数をキーワード引数として渡せるようになった。

An example of passing initial parameter to reduce()
>>> from functools import reduce
>>> reduce(lambda x, y: x + y, range(5))
10
>>> reduce(lambda x, y: x + y, range(5), initial=-10)
0

getpass

関数 getpass() がキーワードオプション引数 echo_char を備えた。キーボードフィードバックを実現する。タイプするたびにダミー文字を表示し、削除されると消去する。

An example of using echo_char parameter
from getpass import getpass

pin = getpass('Enter PIN: ', echo_char='*')

heapq

次の最大ヒープ関数を搭載した:

  • heapify_max()

  • heappush_max()

  • heappop_max()

  • heapreplace_max()

  • heappushpop_max()

公式文書にある、ストリーミング入力から中央値を求めるアルゴリズムコードは必読。

io

ファイルやその他のストリームから読み書きするための汎用プロトコルが追加:

  • Reader[T]

  • Writer[T]

T は通常 str または bytes となるが、ストリームから読み書き可能である型ならば何でもかまわない。これらのプロトコルは typing.IO 系プロトコルのより簡素な代替型だ。

json

CLI が python -m json でいけるようになった。

math

このモジュールが示すエラーメッセージ math domain error が状況に応じた、より詳しい説明に改善した。

Python 3.13 と 3.14 との間の math からのエラーメッセージの違い
$ mamba run -n python-3.13 python -c "import math; math.sqrt(-5)"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
    import math; math.sqrt(-5)
                 ~~~~~~~~~^^^^
ValueError: math domain error
$ mamba run -n python-3.14 python -c "import math; math.sqrt(-5)"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
    import math; math.sqrt(-5)
                 ~~~~~~~~~^^^^
ValueError: expected a nonnegative input, got -5.0

mimetypes

CLI が実装された。下の例のように利用できる:

Examples of running python -m mimetypes
$ python -m mimetypes filename.png
type: image/png encoding: None
$ python -m mimetypes --extension text/javascript
.js

operators

次の述語関数が加わった:

  • is_none()

  • is_not_none()

os

関数 reload_environ() が加わった。この関数の目的は、プロセス外部で環境変数が変更されたときに、値 os.environ を更新できるようにするものだ。

pathlib

クラス Path にファイルとディレクトリーを再帰的に運ぶ次のメソッドが加わった:

  • copy(), move(): 宛先にファイルまたはディレクトリー木をコピーまたは移動

  • copy_into(), move_into(): 宛先ディレクトリーの中にコピーまたは移動

性質をおおまかに整理しておく:

  • いずれも戻り値として Path オブジェクトを返す

  • 宛先が既存ファイルの場合は自身で上書きする

  • 引数 preserve_metadata は既定値が False であることに注意したい

  • {copy,move}_into() の宛先ディレクトリーは存在していることが必須

pdb

機能がたくさん増えたようだが、理解できるものが少ない。

  • コマンド python -m pdb -p PID を実行するとプロセス ID が PID である Python プロセスに対してデバッガーセッションを開始できるようになった。

  • ユーザーがインラインモードでデバッグセッションを終了しようとすると、確認プロンプトが表示されるようになった。ユーザーが了承すると終了が確定され、関数 sys.exit() が呼び出されることで停止する。

  • インラインブレイクポイントは、スキップパターンがあるような場合にはそれを無視し、呼び出しフレームでプログラムを停止するように変わった。

  • デバッグセッションでの複数行入力において、行頭にある Tab 文字は空白字四字分の字下げに変換されるように変わった。

  • デバッグセッションでの複数行入力において、自動字下げが機能するようになった。コードブロックを認識すると、次のどちらかに動作する:

    • 最後の行の字下げを保つ

    • 空白字四字分の字下げを施す

  • pdb.set_trace_async() が追加されたことで、asyncio コルーチンのデバッグをやりやすくなった。この関数を使用するのは await を使用した async 関数内だ。そして、この関数によってデバッガーが起動した場合、await 文が使用可能になる。

  • デバッグセッションでソースコードが構文強調表示されるようになった。この機能の構成方法は 上述 の対話型シェルと同様のものが採用可能であるほかに、pdb.Pdb の引数 colorize でも制御可能だ。

読者ノート

python -m pdbsudo 実行する場合には Python 環境がシステム本来のものに変わらないように配慮しろ。

re

  • メタキャラクター z が使用可能になった。意味は大文字版と同じ。

  • メタキャラクター B が空文字列に合致するようになった。これにより、このメタキャラクターの意味はいつでもメタキャラクター b と反対になる。

types

types.UnionTypetyping.Union の別名に変わった。

`types.UnionType のほうが変わった
>>> import types
>>> types.UnionType
<class 'typing.Union'>

typing

  • 上述のように、types.UnionTypetyping.Union の別名となったことにより、旧式の Union[int, str] と新式の int | str の両方が同一ランタイム型オブジェクトを生成する。これにより両構文の動作が統一した。ただし、実行時に型を introspect するような処理をするコードがある場合、影響を与える可能性のある動作上の差異は存在する。私は気にしなくていい。

  • 別名に対して星分割が効くようになった:

    公式より引用
    >>> type Alias = tuple[int, str]
    >>> type Unpacked = tuple[bool, *Alias]
    >>> Unpacked.__value__
    tuple[bool, typing.Unpack[Alias]]
    

unicodedata

Unicode データベースが Unicode 16.0.0 に更新した。

See also

Unicode 16.0.0

unittest

  • 出力が色による強調表示されるようになった。先述の環境変数 により制御することが可能。

  • Pytest 利用者はおそらく使わないだろうが、クラス TestCaseassert 系メソッドがいくつか追加:

    • assert{,Not}HasAttr()

    • assert{,Not}IsSubclass()

    • assert{,Not}{Starts,Ends}With()

uuid

CLI python -m uuid にオプション --count が使用可能になった。UUID を一度の実行で複数個生成する。これは uuidgen にない機能だ。

Optimizations

ここは一般プログラマーには重要ではないかもしれない。ほとんどチェックしていない。

Removed

asyncio

関数 get_event_loop() はイベントループが存在しない場合に暗黙的にイベントループを生成しないようになった。例外 RuntimeError を送出する。

万が一、古いコードで get_event_loop() を使用するものを持っているようならば、関数 run() を使ったコードに書き換えろ。

itertools

関数 copy(), deepcopy() などが取り除かれた。そもそも itertools が作り出す反復子オブジェクトを再帰的に複製することがこれらの関数は一般的にはできなかったらしい。

今度からは tee() を用いるのが良かろう。

Deprecated

古いやり方をいつまで経っても採用し続けないように、一通りチェックする。文書化されていない機能や特定のプラットフォーム固有の挙動に関するものがほとんどだ。

  • codecs.open() ではなく、単に open() を使え。

  • os.popen() および os.spawn* 系関数を新しいコードで使うな。モジュール subprocess を使え。

Porting to Python 3.14

本節以降、個人的には対応項目なし。


興味がある項目は以上?