LoginSignup
113
64

More than 1 year has passed since last update.

Python3.12の新機能 (まとめ)

Last updated at Posted at 2023-03-12

はじめに

Python 3.5から What's Newの内容をまとめる記事を投稿してきました。

リリース前に次の新機能を先取り的に紹介を始めて今回で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 ximport 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を使うようになりました。

  • 子プロセスウォッチャーのMultiLoopChildWatcherFastChildWatcherAbstractChildWatcherSafeChildWatcherは廃止予定となり、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の呼び出し時のオーバーヘッドも削減できます。

廃止予定

  • typing.Hashabletyping.Sizedcollections.abc.Hashablecollections.abc.Sizedのエイリアスになります。

機能削除

  • PEP 632, distutilsパッケージの削除
    • disutilsは標準ライブラリに含まれていましたが、setuptools経由で使うことを勧められてきました。そして、setuptoolsdistutils相当の機能を自分で持ってしまっていて、distutilsへの依存関係がなくなっています。さらに、pipdistutilsのインストール要求を暗黙のうちにsetuptoolsとすり替えてしまいます。ということで、すでに distutilsを使っている人はいないので削除することになりました。

まとめ

Python 3.12の変更点についてまとめてみました。5月のベータリリースまでは機能追加が続くのでこれから何度かアップデートしていくことになると思います。また、面白そうな新機能があれば別記事にするかも知れません。

113
64
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
113
64