はじめに
Python 3.5から What's Newの内容をまとめる記事を投稿してきました。
- Python3.5の新機能
- Python3.6の新機能
- Python3.7の新機能
- Python3.8の新機能(まとめ)
- Python3.9の新機能(まとめ)
- Python3.10の新機能(まとめ)
- Python3.11の新機能(まとめ)
リリース前に次の新機能を先取り的に紹介を始めて今回で8回目です。最初に始めた頃はこんなに長く続けるとは思っていませんでしたが、年中行事になっているので今回もまとめていきます。
次は3.12で、開発ロードマップ(PEP-693)はこの様になっています。
- 3.12.0 開発開始: 2022-05-08 (完了)
- 3.12.0 alpha 1: 2022-10-24 (完了)
- 3.12.0 alpha 2: 2022-11-14 (完了)
- 3.12.0 alpha 3: 2022-12-06 (完了)
- 3.12.0 alpha 4: 2023-01-10 (完了)
- 3.12.0 alpha 5: 2023-02-07 (完了)
- 3.12.0 alpha 6: 2023-03-07 (完了)
- 3.12.0 alpha 7: 2023-04-03
- 3.12.0 beta 1: 2023-05-08 (これ以降は新たな機能の追加は行わない)
- 3.12.0 beta 2: 2023-05-29
- 3.12.0 beta 3: 2023-06-19
- 3.12.0 beta 4: 2023-07-10
- 3.12.0 candidate 1: 2023-07-31
- 3.12.0 candidate 2: 2023-09-04
- 3.12.0 final: 2023-10-02
今回は書き初めが少し遅くなってしまって、すでにalpha 6が出ています。ベータまであと2ヶ月弱で機能の実装の方もだいぶ進んでいるのではないかと思います。
更新履歴
2022-03-12
- 最初のバージョン。a6が 2023-03-にリリースされましたが、そのwhat's new をベースに書いています。
注目した新しい機能
エラーメッセージの改善
- トップレベルで
NameError
を出す時に、対象の名前が標準ライブラリ名の場合は「もしかしてインポートし忘れている?」というメッセージを出すようになりました。
3.11以前
>>> sys.version_info
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'sys' is not defined
3.12以降
>>> sys.version_info
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'sys' is not defined. Did you forget to import 'sys'?
- メソッド内で
NameError
を出す時に、対象の名前がそのインスタンスの属性名の場合には「もしかして、selfをつけ忘れてる?」というメッセージを出すようになりました。
>>> class A:
... def __init__(self):
... self.blech = 1
... def foo(self):
... somethin = blech
...
>>> A().foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in foo
NameError: name 'blech' is not defined. Did you mean: 'self.blech'?
-
from y import x
をimport x from y
と間違えて書いた時のSyntaxError
で「もしかして from ... import って書こうとした?」というメッセージを出すようになりました。
>>> import a.y.z from b.y.z
File "<stdin>", line 1
import a.y.z from b.y.z
^^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: Did you mean to use 'from ... import ...' instead?
-
from <module> import <name>
で名前が見つからずにImportError`を出す時に「もしかしてこのこと?」というメッセージが出るようになりました。
>>> from collections import chainmap
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: cannot import name 'chainmap' from 'collections'. Did you mean: 'ChainMap'?
Linux perfプロファイラーのサポート
-Xperf
オプションをつけるか、PYTHONPERFSUPPORT
環境変数をセットして実行すると、perf record
コマンドで作成するのと同じperf.dataファイルを生成できます。これを perf report
コマンドにかけるとプロファイル結果を見ることができます。また``sys.activate_stack_trampoline()と
sys.deactivate_stack_trampoline()`を使ってプログラム内でプロファイルデータの生成を明示的に書くこともできます。
その他の言語の変更
-
types.MappingProxyType
型のインスタンスは元のマッピングがハッシュ可能であればハッシュ可能になります。 -
memoryview
で2バイト浮動小数点型を扱えるようになります (フォーマットコード “e”)。 -
NULLバイトを含む含むソースコードは
SyntaxError
になります。 -
NULLバイトを含むソースコードをパースすると
ast.parse()
はValueError
の代わりにSyntaxError
を返すようになります。 -
ガベージコレクション(GC)の動作タイミングが変わり、オブジェクトの割り当て時ではなく、Pythonバイトコード評価ループ中の「評価ブレーカー」メカニズムで実行されます。加えて、Pythonコードを実行せずに長時間動作するC言語拡張でもGCが呼ばれるように、
PyErr_CheckSignals()
が呼ばれるタイミングでも実行されます。 -
正しいエスケープシーケンスではないバックスラッシュと文字列のペアは
DeprecationWarning
ではなくSyntaxWarning
を発生させることになります。例えば、re.compile("\d+\.\d+")
はSyntaxWarning
を出すので、正規表現にはre.compile(r"\d+\.\d+")
という風にraw文字列を使ってください。将来的にはSyntaxWarning
ではなくSyntaxError
が出されることになります。 -
0o377
以上の8進数えスケープ(例えば "\477")はSyntaxWarning
を出すようになります。これも将来的にはSyntaxError
になります。 -
ブール型を引数に取る全ての組み込み関数、拡張関数はブール型、整数型だけでなくその他の型の値も引数として受けとれるようになります。
-
内包表記の中で代入式を使えるようになります
-
スライスオブジェクトがハッシュ可能になり、辞書型のキーやセットのアイテムとして使えるようになります。
新規に追加されたモジュール
(まだありません)
モジュールの改善
array
-
array.array
でタイプ指定ができるようになりました(例えばarray.array[int]
のように)
asyncio
-
Linuxでは、
os.pidfd_open()
が利用可能な場合は、asyncio
はデフォルトでThreadedChildWatcher
の代わりにPidfdChildWatcher
を使うようになりました。 -
子プロセスウォッチャーの
MultiLoopChildWatcher
、FastChildWatcher
、AbstractChildWatcher
、SafeChildWatcher
は廃止予定となり、Python 3.14で削除されます。子プロセスウォッチャーをマニュアルで設定することは推奨されず、イベントループが各プラットフォームで最適な子プロセスウォッチャーを自動で選びます(PidfdChildWatcher
が利用可能なときはそれを使い、そうでなければThreadedChildWatcher
を使います)。 -
asyncio.set_child_watcher()
、asyncio.get_child_watcher()
、asyncio.AbstractEventLoopPolicy.set_child_watcher()
、asyncio.AbstractEventLoopPolicy.get_child_watcher()
は廃止予定となり、Python 3.14で削除されます。 -
カスタムのイベントループファクトリーを設定できるようにするために、loop_factoryパラメータが
asyncio.run()
に追加されます。 -
C言語実装の
asyncio.current_task()
が追加され、4~6倍の速度向上を得られます。
pathlib
-
walk()
が追加され、ディレクトリーツリーを走査してその配下の全てのディレクトリとファイルのリストを作ります。 -
pathlib.PurePath.relative_to()
のオプショナルパラメーターとして walk_up が追加され、..
を含む結果を得ることができます。 -
os.path.isjunction()
の代替として、pathlib.Path.is_junction()
が追加されます。
最適化
-
PEP 623 Unicodeからwstrを削除
- Python 3.3でUnicodeの幾つかのAPIを削除した際に、Unicodeオブジェクトに
wstr
とwstr_length
というメンバーを追加しました。Python 3.12でそれが削除されます。それによって文字列ひとつあたり8バイトのメモリーが節約できます。また、Unicode関連APIの呼び出し時のオーバーヘッドも削減できます。
- Python 3.3でUnicodeの幾つかのAPIを削除した際に、Unicodeオブジェクトに
廃止予定
-
typing.Hashable
とtyping.Sized
はcollections.abc.Hashable
とcollections.abc.Sized
のエイリアスになります。
機能削除
-
PEP 632,
distutils
パッケージの削除-
disutils
は標準ライブラリに含まれていましたが、setuptools
経由で使うことを勧められてきました。そして、setuptools
はdistutils
相当の機能を自分で持ってしまっていて、distutils
への依存関係がなくなっています。さらに、pip
はdistutils
のインストール要求を暗黙のうちにsetuptools
とすり替えてしまいます。ということで、すでにdistutils
を使っている人はいないので削除することになりました。
-
まとめ
Python 3.12の変更点についてまとめてみました。5月のベータリリースまでは機能追加が続くのでこれから何度かアップデートしていくことになると思います。また、面白そうな新機能があれば別記事にするかも知れません。