2017年12月13日

最近のPython-dev(2017-12)

はてなブックマークに登録

バックナンバー: 9月号 | 8月号 | 6月号 | 5月号 | 4月号 | 3月号 | 2月号 | 1月号

@methane です。 ISUCON があってしばらく間が空いてしまいました。コミットやML上の議論も追えてないのですが、1月末にPython 3.7のbeta1 (=feature freeze)が予定されているために、Python 3.7 を目標にしている PEP たちがたくさんacceptされたので、それらを紹介しておきます。

PEP 540 UTF-8 mode

https://www.python.org/dev/peps/pep-0540/

PEP 538 (locale coercion) とセットで、私が BDFL-delegate (PEP を accept する責任者) になった PEP です。

この PEP は当初はかなりのボリュームが有ったのですが、すでに PEP 538 を accept したので、それを補完する機能として大幅にシンプル化しました。

PEP 538 では、起動時に locale が C であったときに、 LC_CTYPE を C.UTF-8 などへの変更を試みます。 また、C locale では標準入出力のエラーハンドラが surrogateescape になり、例えば stdin から読んだ文字列をそのまま stdout に書く場合などに非ASCII文字に対してもバイト透過な振る舞いをするのですが、それを C.UTF-8 などの coercion ターゲットとなる locale にも適用します。

PEP 540 も、 locale を変更しない以外は全く同じ振る舞いをするようになりました。具体的には次のとおりです。

  • stdin, stdout の encoding/error handler が UTF-8/surrogateescape になる
  • sys.getfilesystemencoding() と locale.getpreferredencoding() が UTF-8 を返す

PEP 538 と違って実際の locale は変更されないので、例えば readline で日本語入力はできないままですが、C locale 以外存在しないコンテナ等で Python を動かすときにデフォルトでUTF-8を使ってほしいというような用途にはこれで十分です。

PEP 563 Postponed Evaluation of Annotations

https://www.python.org/dev/peps/pep-0563/

from __future__ import annotations を書くことで、関数アノテーションが評価されず、ただの文字列になります。とはいえ、ソースを読むときに構文としてはチェックされるので、任意の文字列がかけるわけではありません。

これにより、アノテーションを書くことによる性能のオーバーヘッドを減らす効果があるのと、アノテーション部分の名前解決のための forward references が不要になって書くのが楽になるという効果があります。

この動作は Python 4 からデフォルトになる予定なので、 Python 3.7 に移行した人は早めにこの動作を有効にすることをおすすめします。

個人的には、実行時に評価されなくなることで、Python の構文を実行時には許されない形で利用したり、あるいはアノテーション部分でしか利用できない構文を追加するという進化への道が開けたという点でも期待しています。例えば現在 Union[int, str] と書いている部分を int or str あるいは int | str と書けるようにする提案ができるかもしれません。(前者は評価するとただの int になり、後者は評価すると | が処理できずに TypeError になる)

PEP 560 Core support for typing module and generic types

https://www.python.org/dev/peps/pep-0560/

いままで type hint は Python 3 で追加された関数アノテーション以外には特別な Python に対する機能追加を必要としないように設計されてきましたが、 typing がある程度の成功を収めて来ているので、そろそろ typing の問題を解決するために Python 自体に手を入れてもいれようというのがこの PEP です。

例えば、 typing.Listclass List(list, MutableSequence[T], extra=list): ... として宣言されています。 この MutableSequence[T] の部分ですが、親クラスになるためにクラスでないといけないという制限があります。そのために実際に親クラスになってしまうので実際にメソッドを提供していないクラスが大量にMROに入りメソッド呼び出し性能のオーバーヘッドが大きくなるという問題があります。また、 MutableSequence 自体もクラスなので、それに対して [T] と書けるようにするためにメタクラスが使われています。

このために現在の typing は大量のメタクラスハックを必要とし、実行時オーバーヘッドもかかり、 import typing も遅くなり、また他のメタクラスとの衝突解決の手間が発生するという欠点を背負っています。

これを解決するために、 Python に次の機能を追加します。

  • class 文の親クラスリスト部分に、 type オブジェクトではない __mro_entries__ メソッドを持つオブジェクトを書くことができる
  • __class_getitem__ メソッドを定義すると、メタクラスを使わなくても MyClass[int] のようにクラスに添え字を書くことができる

これらの機能は typing モジュール以外から使えないというわけではありませんが、 typing 以外の用途での利用は非推奨になっています。

とはいえ、 __class_getitem__ については、最近のメタクラスを使わなくてもクラスの振る舞いをカスタマイズできる流れに添っていて黒魔術感も比較的少なめなので、本当にクラスオブジェクトに添え字アクセスが必要な場面であれば、typing 以外で使っても良いんじゃないかな。

PEP 561 -- Distributing and Packaging Type Information

https://www.python.org/dev/peps/pep-0561/

Typing が本格的に使われていくためには、サードパーティーライブラリの型情報をどうやって配布・利用するかを決めなければなりません。ということでそれを決めたのがこの PEP です。

PEP 562 -- Module getattr and dir

https://www.python.org/dev/peps/pep-0562/

モジュールに __getattr__ 関数を定義して遅延ロードや利用時warningなどを実現する仕組みです。

また、遅延ロードされる名前を提供するために __dir__ を利用することもできます。

個人的には、 import asyncio で芋づる式に multiprocessing まで import されているのを、 concurrent.futures.ProcessPoolExecutor を遅延ロードすることで解消したいと思っています。

PEP 565 -- Show DeprecationWarning in main

https://www.python.org/dev/peps/pep-0565/

Python には廃止予定のAPIについて警告するための DeprecatedWarning がありますが、これはPython製アプリケーションのユーザーにとってはほぼ無意味で混乱させるものなので、現在はデフォルトで表示されないようになっています。

しかし、 Python 開発者でもこの警告を有効にしていない人が多いために、DeprecationWarning に気づかれないという悩ましい状況も発生しています。

PEP 565 はこのバランスを少しだけ調整する提案です。 __main__ モジュールにおいてだけ、 DeprecationWarning をデフォルトで表示するようにします。

__main__ モジュールとは、インタラクティブシェルや Python インタプリタに渡された実行ファイルのことです。そこで直接廃止予定のAPIが呼ばれたときだけ DeprecationWarning が表示されるようになります。

これにより、開発者がAPIの使い方を調べるなどの目的でインタラクティブシェルで廃止予定のAPIを実行したときに Warning に気づけるようになると期待できます。

とはいえ、これの効果は限定的なので、Python開発者は -Wdefault オプションを使うか、 PYTHONWARNINGS=default と環境変数を設定しておきましょう。

-X dev option

https://docs.python.org/dev/using/cmdline.html#id5

上で紹介した -Wdefaultオプションに加えて、 Python 拡張モジュール開発者向けのものも含めて、幾つかの開発者向けオプションをまとめて有効にするオプションとして -X dev オプションが追加されました。

また、 PYTHONDEVMODE=1 という環境変数でも dev mode を有効にできるようになります。

PEP 557 -- Data Classes

https://www.python.org/dev/peps/pep-0557/

ちょうど Qiita に紹介記事があったのでそちらを参照してください。

Python3.7の新機能 Data Classes

songofacandy at 12:04│Comments(0)Python 

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント