こんにちは!けーじです。
今回は型チェッカーのお話です。Pythonは動的型付け言語と呼ばれる言語で、言ってしまえば型の記述に緩い言語に分類されると思います。決してゆるく書いていいということではなく、型を意識して書くことが重要なのは変わりません。そのような型の取り扱いをサポートしてくれるのが型チェッカーです。
※注意ですが、私は型チェッカーについてすごく明るいというわけではないと思います。調査が至らないところがあるかもしれませんが、温かい目で見守っていただけるとありがたいです。
目次
型チェッカーについて
プログラミング言語には静的型付け言語と動的型付け言語があります。前者は変数を宣言するときにその変数の型も合わせて書くことが強制されます。いちいち型を記述することが煩わしいかもしれないですが、型が合わない時点でエラーを出してくれるので、誤りに早めに気づいて安全に開発できるというメリットがあります。
一方で動的型付け言語は必ずしも型を記載する必要がありません。実際に処理を動かして変数に値が入った時点で自動的に型が決まるようなイメージです。特に型を記述しなくても動くのでコーディング時には楽ではあるのですが、型が意図どおりでなくてもエラーが発生しないので、不具合がある場合に発見が遅くなる可能性があります。Pythonはこちらの動的型付け言語にあたります。
// Javaでは変数宣言時に型の記載が必須
String name = "taro";
int number = 1;
# Pythonでは型は記載しなくてもよい。値をもらってから確定する
number = 1
name = "taro"
このような動的型付け言語の欠点を補うツールとして用いられているのが型チェッカーです。Pythonでは型の記述は必須ではないですが、想定される型を記述することができます。これは型ヒントといって記述しておくと可読性が上がり、他の人がどのようなコードであるかを理解する助けになります。注意点としては、型を強制する効力はないので、int型という変数と型ヒントをつけていても実際にはstr型でもlist型でも利用することができてしまいます。
# Pythonでは型ヒントを書ける。しかし強制力はない
name: str = "taro"
name: str = 1 # strを想定しているがintが入っている。エラーにはならない
型チェッカーによる指摘例
型チェッカーと呼ばれるツールを利用すると、この型ヒントを利用したチェックを走らせることができまして、想定どおりでない型が利用されているところに対してエラーを発生させることができます。Pythonの型チェッカーとして既存のもので有名なものはpyrightとmypyが挙げられると思います。
pyrightについてはvscodeでPythonを記載しているときには使用されている方が多いと思います。Pythonの拡張機能をインストールすると、pylanceというものも一緒にインストールされて、pyrightの機能をベースに提供してくれます。これがあると、コードを記載している間に不整合があった場合に指摘してくれます


mypyはコマンドライン上で実行することがメインのツールになります。一通りコーディングが終わった後にコマンドを叩いて、型で不整合が生じているところがないかを確認する事ができます。コマンドで実行できるのでCIツールに導入される例も多いようです。

これらのツールを利用してPythonの開発が効率よく行われてきていたのですが限界もあります。大規模なプロジェクトになってくると動作に時間がかかったり、そもそも型チェックが完了する前にメモリが足りず完了できないということがあるようです。
また、エディタ上で型を指摘するツールとコマンドライン上で指摘するツールが異なるため、エディタでコーディングしていて指摘がなかったのに、コマンドライン上でチェックしたらエラーが指摘される可能性があります。直せば良い話ではありますが、エラーが残っているならコーディング中に気づきたいところではあります。

Pyreflyについて
このような型チェッカーにMeta社が開発したPyreflyが登場しました。読み方は”パイアフライ”です。ホタルをイメージしているようで、firefly ”ファイアフライ”と同じです。こちらはRust製で作成された型チェッカーです。Python関連のRust製ツールはuvが有名だと思います。こちらは仮想環境の管理を行うツールですが、その特徴はなんといっても動作の早さです。同じRust製であるPyreflyもそのような特徴を引き継いでいます。
Pyreflyのここがスゴイ(爆速)
Instagramのような大規模なプロジェクトになってくると、その型チェックだけでも時間がかかることが予想されます。実際これまで紹介したpyrightやmypyで実行しようとすると、out of memoryとなってしまい、その巨大さゆえにチェックを完了させることすらできないようです。しかし、Pyreflyを用いれば動作を素早く完了させることができると説明されています。以下は発表中のスライドになりますが、数分かかっていた型チェックが数秒のうちに完了したり(PyTorch)、実行できていなかったものも高速にできることが示されています(Instagram)。

デモの中にはmypyとの比較が行われていました。同じファイル群に対してmypyとPyreflyで型チェックを実行している様子が出ていますが、mypyが一度チェックを完了するうちに、Pyreflyでは27回もチェックができていることがわかります。27倍程度早くなることが予想できますね
エディタ上の補完機能についてもpyrightとの比較がありました。こちらは補完が表示されるまでの時間はコードの複雑さに依存しますが、pyrightで8秒ほどかかっていたものが2秒で、65秒ほどかかっていたものが15秒ほどで補完の候補が表示されていました。1/4程度に時間が短縮されるようです。このように実行速度が早いことは、開発体験の快適さに直結するため、導入する価値は高いと思われます。
Pyreflyのここがスゴイ(型推論)
Pyreflyでは高度な型の推論ができることも紹介されています。Pythonでコーディングするときは、型ヒントを書いて可読性をあげることが推奨されていますが、すべての変数に型ヒントが付与されているとは限りません。既存の巨大なコードベースや、開発スピードを優先して型ヒントが省略されているケースも多々あります。型チェッカーは型ヒントを参考に確認していくので、このように型が書かれていないとチェックすることができず、結局あとになってコード実行して初めて分かるといった状況が出てきてしまうかもしれません。
しかし、Pyreflyでは型の記載がない場合でも、どのような型の変数が返ってくるはずかを理解して補完するような機能があります。後で実際にお見せしますが、面白い機能ですし、開発の強力なアシストになる気がします。
ツールの統合(PyreflyだけでOK)
Pyreflyはエディタ上でもコマンドライン上でも利用することができるツールです。そのため、基本的にはエディタ上でエラーを潰してしまえばコマンドライン上で指摘されることはほとんどないでしょう。基本的にはエディタで潰しておくが、安全のためCIにも加えてエラーが出てこないことを確認するといった使い方にはうってつけだと思います。
実際に使ってみた
pyreflyのセットアップ(uv add, pyrefly init)
Pyreflyを使用するには、Pythonの他のライブラリと同様にインストールできます。pip installで導入できますが、私の場合はuvを使用することが多いのでuv addで導入しました。その後、pyrefly init とコマンドを実行してあげるとそれだけでセットアップが完了します。
uv add pyrefly
pyrefly init
vscode上で型チェックをリアルタイムで行うためには拡張機能をインストールします。pyreflyと検索すればすぐに見つかると思います。

Pyreflyによる型チェック
それでは実際に実行してみます。簡単な例ですが、2つのintの変数を受け取ってその和を返す関数です。引数であるaとbがint型であること、返される値がint型であることが記載されています。

上の例ではaddに2つのintの引数を渡しているため、正しく呼び出せています。このときはvscode上で特にエラーは検出されておらず、コマンドライン上でpyrefly check コマンドを実行してもエラーは確認されません。

渡す引数を3.0, 4.0にしてみます。float型を渡していることになりますが、関数としては正しく動作をして7.0を返します。ただし、vscode上ではエラーを示す赤い波線が表示され ます。

カーソルをあてると指摘されている内容が確認できます。これは4.0にあてている画面ですが、引数’b’にはintが入るはずなのにfloatが入っていると指摘されていますね。

コマンドライン上で実行しても同様の指摘が確認できます。表示されているメッセージはvscode上で表示されていたものと全く同じですね。

このようにPyreflyを利用すればエディタ上ですぐに型の不整合が起きていないか確認ができますし、コマンドライン上でも実行できるのでCIに採用することも可能です。
型推論の実施
もう一つの特徴として紹介して型推論についても確認してみましょう。発表で実際に使用されていた例を書いてみます。はじめにPyreflyの機能をoffにしてpylanceを有効化してみます。例えば、以下のように。str型の変数が入っているnameの後に、ドットを入力するとstr型が持つ、次に入力されうる候補を挙げてくれます。

一方で、以下のようにget_names関数を定義して、その返り値に対して同じことをしてみます。get_namesの中身を見ると、リストを作成してその中にstr型である”body”と”main”を入れているだけなので、get_names()[0] と記載するとstr型の”body”が取り出されるのは明白です。しかし、型ヒントがないため、先程のような補完機能は表示されません。

ここでpylanceを無効にして、Pyreflyを有効にしてみます。すると、先程は表示されなかった補完機能が表示されるようになりました。内容もstr型で表示されたものと同じで、Pyreflyでstr型だと読み取って表示してくれているのがわかります。get_names関数の定義を見ると、灰色で型ヒントが追加されています。これは私が入力したものではなく、Pyreflyで自動的に表示してくれるものになります。このように、型ヒントが書かれていなくても、Pyreflyがうまい感じで読み取って開発者のサポートをしてくれるのは大きな強みではないかと思います。

注意事項
以上のように、Pyreflyについて語ってきましたが、こちらは正式版ではなくベータ版のようです。正式版ではないので不具合などが生じる可能性もあると思うので、使用を検討する際には注意していただければと思います。
まとめ
以上、Pyreflyを紹介いたしましたが、仮想環境にuv、リンタ・フォーマッタとしてruff、型チェッカーとしてpyreflyと揃えていくと、Rust製で基本的なツールが揃いそうです。正式版がリリースされたら積極的に使用していきたいと考えています。
参考資料
- https://pyrefly.org/ Pyreflyの公式ページです。開くとホタルのように光がゆらゆら動いているデザインのページが表示されます。動作の早さをアピールするため、mypyやpylanceとあわせて動作時間を表示していますね
- https://www.youtube.com/watch?v=hlJlzEbSYZg 今回参考にしたyoutubeの動画です。9月ごろの動画のようですので、ベータ版よりも前の情報かもしれないです(ベータ版のリリースは11月)。動作の早さや型推論の様子が動画でわかるのでおすすめです。

コメントを残す