ENGINEER BLOG ENGINEER BLOG
  • 公開日
  • 最終更新日

AWS Lambda の Python に pyright の strict モードを入れてみた

この記事を共有する

目次

はじめに

こんにちは!パーソル&サーバーワークスの野間です。

これまでのブログでは、AWS Lambda(以下、Lambda)の Python コードに ruff を導入した話をご紹介しました。
最近は Python を勉強しながら関数を書いているのですが、少し書けるようになってきた一方で、実行して初めてエラーに気づくことが増えてきました。
書いている途中で間違いに気づける仕組みが欲しくなり、型チェッカーの pyright を入れてみました。

そもそも型チェッカーとは

Python は変数の型を書かなくても動く言語です。
そのぶん、文字列を渡すべきところに数値を渡しても、実行するまで気づけません。

型チェッカーは、コードを実行せずに「この値はここに渡せない」と教えてくれるツールです。
私のように書きながら覚えている段階だと、実行前に間違いを止めてくれるのはかなり助かります。

厳しさのモードを選ぶ

pyright には型チェックの厳しさを決める typeCheckingMode という設定があり、以下の 4 つから選びます。
何も指定しない場合は standard になります。

  • off:型チェックはしない。文法の誤りだけを報告する
  • basic:よくある間違いを捕まえる程度の、少なめのルール
  • standard:basic にルールを追加したもの。既定値
  • strict:ほとんどのルールを有効にする

各モードで有効になるルールの違いは pyright の設定ドキュメント にあります。

厳しいほど早く間違いに気づけるはずだと考えて、一番厳しい strict から始めました。
設定は pyrightconfig.json に書きます。

{
  "pythonVersion": "3.12",
  "typeCheckingMode": "strict"
}

strict をそのまま入れるとどうなるか

この状態で実行すると、大量のエラーが出ました。
中身を見ると、そのほとんどが自分の書いたコードではなく boto3 の戻り値の型が分からないという指摘でした。

pyright-strict-01.png

boto3 は呼び出すサービスによって戻り値の形が変わるため、型が付いていません。
そのため「この値の型が推論できない」という警告が、AWS の API を呼ぶたびに出ます。

自分のコードの問題ではないので、ここを全部直しても品質は上がりません。
かといって strict をやめると、型注釈を書かせるルールまで一緒に消えてしまいます。

残したルールと切ったルール

そこで strict を土台にしつつ、boto3 起因のルールだけを個別に切りました。

残したのは、自分が書く部分に効くルールです。

"reportMissingParameterType": "error"

これは関数の引数に型注釈が無いとエラーにするルールです。
今回の目的は「自分の書いた関数の入出力をはっきりさせる」ことなので、ここは強制のままにしました。

切ったのは、推論できない型を責めるルールです。

"reportUnknownMemberType": "none",
"reportUnknownVariableType": "none",
"reportUnknownArgumentType": "none",
"reportUnknownParameterType": "none",
"reportMissingTypeArgument": "none"

いずれも「型が分からない」ことを指摘するもので、boto3 を使う限り消えません。
指摘の理由が自分の側に無いルールは切る、という基準で選びました。

最初はルールを 1 つずつ切っては実行し、を繰り返していたのでかなり時間がかかりました。
エラーメッセージの末尾にルール名が出るので、そこを見て切る対象を決めるのが早いです。

pyright-strict-02.png

Lambda Layer を使っている場合はパスを通す

ここは Lambda 固有の話です。

共通コードを Lambda Layer に置いていると、pyright がその import を解決できません。
Layer は実行時に /opt へ展開されるので、ローカルのディレクトリ構成とパスが一致しないためです。

extraPaths に Layer のディレクトリを追加すると解決します。

"include": ["src", "tests", "layers/common/python"],
"extraPaths": ["layers/common/python", "src"]

AWS Serverless Application Model を使っている場合、Layer のディレクトリ構成は決まっているので、ここを一度書けば以降は触りません。
これを入れないと共通コードの import がすべてエラーになるので、Layer を使っているなら最初に設定してください。

boto3 の型は使うサービスごとに足す

boto3 の型を補うには boto3-stubs を入れます。
このパッケージは全サービス分の型を一度に入れるのではなく、使うサービスを指定して入れる形です。

boto3-stubs[dynamodb,logs,ssm,stepfunctions]

新しい AWS サービスを呼び始めたときは、ここに追記する必要があります。
実際、あとから AWS Cost Explorer を呼ぶ処理を足したときに型が付かず、ce を追加して解決しました。

指定できるサービス名は boto3-stubs のドキュメント にあります。
入れ忘れると「型が分からない」に戻るだけでエラーにはならないので、気づきにくい部分です。

まとめ

今回は Lambda の Python コードに pyright の strict モードを導入しました。

一番の学びは、厳しい設定をそのまま使うのが正解とは限らないということでした。
勉強中の身としては「一番厳しくしておけば安心」と考えがちだったのですが、指摘の理由が自分の側にあるかどうかで選ぶ、という基準を持てたのは収穫でした。

ruff を入れたあとに何を足すか迷っている方の参考になれば幸いです。

この記事は私が書きました

野間 太一

記事一覧

猫とCloudFormationが好きです。

野間 太一

この記事を共有する

クラウドのご相談

CONTACT

クラウド導入や運用でお悩みの方は、お気軽にご相談ください。
専門家がサポートします。

サービス資料ダウンロード

DOWNLOAD

ビジネスをクラウドで加速させる準備はできていますか?
今すぐサービス資料をダウンロードして、詳細をご確認ください。