Python3.7について何が変わったのかを、わかりやすく解説していきます。
実際にドキュメントを読んだり、試したりしてみて、おおまかな変更点は、
- 型ヒント関係のアップデート
- 速度改善
- asyncioの改善
などがありました。
今回はそんなPython 3.7.0で気になる新しい機能や改善点をまとめてみます。
リリースハイライト
新たな文法を導入した変更
- PEP-563 アノテーションの評価を遅らせる
過去互換性のない文法変更
asincとawaitが予約語になりました。
新たなライブラリモジュール
新たな組み込み機能
- PEP-553 組み込みブレークポイント
Pythonデータモデルの改善
- PEP-562 モジュール属性へのアクセスをカスタマイズ
- PEP-560
typing
モジュールとジェネリック型のコアサポート - 辞書型オブジェクトが挿入順を保持する事が正式にPython言語の仕様として宣言された
標準ライブラリの特筆すべき改善
asyncio
モジュールは新機能の追加やユーザビリティ及び性能の改善が行われたtime
モジュールはナノ秒解像度の関数のサポートが追加された
CPython実装の改善
C APIの改善
PEP-539 スレッド局所記憶にアクセスするための新たなC言語API
ドキュメントの改善
新機能
PEP-563 アノテーションの評価を遅らせる
PEP-3107で提案されて、PEP-0526で改善されたアノテーション機能により型ヒントを与えられるようになりました。
ですが、それによって二つの少しだけ目立つユーザビリティの問題が起こりました。
つまり、定義前の名前にアノテーションは付けられない(前方参照することができない)
アノテーション付きのソースコードはPythonプログラムのスタート時間に悪影響があります。
この問題を解決するために、アノテーションの評価をコンパイル時から実行時に必要な時のみ行われるよう変更することにより、前方参照もできるようになったし、スタート時間も早くなりました。
PEP-538 過去の遺物であるCロケールの抑制
Pythonインタプリターのコマンドラインインターフェースで、
Cロケール(POSIXロケール)を設定していたとしても、強制的にC.UTF-8、C.utf8、UTF-8のどれかに変更して実行を行うというものです。
これにより、ロケールを解釈するC拡張モジュール(readlineなど)はASCIIの代りにUTF-8をデフォルトエンコーディングとして動作します。
この動作は新たに導入されるPYTHONCOERCECLOCALEという環境変数によって制御が可能(0にすると以前のバージョンの動作に戻る)。
また、これに伴いstdinとstdoutのデフォルトエラーハンドラーはsurrogateescapeになる。stderrはロケールに関わらずbackslashreplaceのまま。
PEP-540 UTF-8モードの追加
UTF-8モードが追加された。このモードではLocaleは無視してUTF-8エンコーディングが用いられる。
そして、標準入出力のエラー処理には surrogateescapeが使用されます。このモードはPOSIX Locale以外ではデフォルトでオフになっているが、コマンドラインで -X utf8を付けるか、PYTHONUTF8環境変数を設定することでオンにすることができる。
PEP-553 組み込みブレークポイント
breakpoint()
という組み込み関数を追加して、簡単に一貫性のある方法でデバッガを起動できるようにする。
この関数はsys. breakpointhook()
を呼び出す。
このフックはデフォルトでは、pdbをインポートしてpdb.set_trace()を呼び出すという動作をするが、自分で他の関数をバインドすることも可能。
あるいは、新設のPYTHONBREAKPOINT
環境変数に同様にセットすることも可能だし、この環境変数を0に設定すればbreakpoint()
機能を無効化もできる。
PEP-539 スレッド局所記憶にアクセスするための新たなC言語API
一つのプロセス内のスレッドは通常アドレス空間を共有しているが、スレッド毎に独立した記憶領域が欲しい場合がある。
その為に各種プラットフォームで用意されている仕組みが
スレッド局所記憶(Thread local storage)である。
Pythonでは従来Thread Local Storage(TLS) API というAPIでこれにアクセスしていたが、Keyの値が整数であるという想定を置いていた。
これは全てのプラットフォームで成り立つ想定ではないため、新たにThread Specific Storage (TSS) APIを定義し、これによってTLS APIを置き換えることとした。
PEP-562 モジュール属性へのアクセスをカスタマイズ
モジュールレベルで__getattr__()
を定義することができ、それによってモジュール属性へのアクセスをコントロールできるようになった。
それにより、例えば非推奨の属性に対するアクセスが有った場合に警告メッセージをこれまでよりも容易に出せるようになった。
PEP-564 ナノ秒の精度を持つ新たな時間関数
従来の時間関数のナノ秒精度を持つバージョンが追加された。
- time.clock_gettime_ns()
- time.clock_settime_ns()
- time.monotonic_ns()
- time.perf_counter_ns()
- time.process_time_ns()
- time.time_ns()
5分でわかる!人気プログラミング言語"Python"とは
PEP-565 __main__で非推奨の警告を出す
Python 2.7と3.2で非推奨警告をデフォルトで出さない変更を加えたが、非互換の変更に事前に気がつくという本来の目的を果たせなくなっていた。
そこで、そのモジュールが __main__
で呼び出された時には非推奨警告を出すようにした。
PEP-560 typing
モジュールとジェネリック型のコアサポート
当初、PEP-484はCPythonのコアに変更を加えずに導入できるよう設計されていた。
ところが最近になり、型ヒントやtyping
モジュールがコミュニティの中で広く使われるようになってきたので、この制限を取り払うこととした。
このPEPで、__class_getitem__()
と__mro_entries__
という二つのメソッドを導入し、typing
モジュールのほとんどの構成要素から使うようにした。
結果として、型に関する様々な操作が最大7倍早くなり、ジェネリック型をメタクラスの衝突無しに利用したりできるようになった。またこれにより、長い間解決されずにいたバグのいくつかが修正された。
"Python"の基本 Webフレームワーク[Django, Flask, Bottle]
開発実行時モードの追加: -X dev
コマンドライン・オプションに -X dev が追加され、サポートする環境変数にもPYTHONDEVMODE
が追加された。
これらを指定すると、デフォルトで有効にするにはオーバーヘッドのかかりすぎる実行時チェックなどが追加で実行される。
PEP-552ハッシュを利用したpycファイル
Pythonはバイトコードコンパイルした結果をpycファイルにキャッシュとして格納する。
その際に、元ファイルの最終更新時刻とサイズをpycファイルのヘッダに記録しておき、再コンパイルが必要かどうかを判断するのに使っていた。
これは効率的ではあるが欠点もある。
ファイルシステムの時刻の解像度が荒かったりすると再コンパイルが必要なのにしなかったりして混乱をもたらす可能性がある。
また、時刻をキャッシュファイルに記録するのでビルドの再現性の点で問題になったりもする。
PEP-552では元ファイルのハッシュをpycファイルに記録出来るようにする拡張を提案している。
通常の利用では引き続き時刻を元にした判断が行われハッシュをpycに記録することは無いが、ハッシュを利用したpycはpy_compile
やcompileall
などのモジュールで生成することができる。
ハッシュを記録したpycファイルには二種類有る。python実行時に更新確認をするものとしないものである。更新確認しないものは、外部のビルドシステムでpycの更新確認をする場合に有用である。
まとめ
今回のアップデートで、モジュールが改善されたものがあるので、また機会があればご紹介したいと思います。