概要
AWS LambdaでPythonコードを実装していたら以下のエラーに遭遇しました。
[ERROR] Runtime.ImportModuleError: Unable to import module 'app.main': No module named 'pydantic_core._pydantic_core'
こちらの原因と解決方法を紹介します。
前提と原因
まず、前提として、AWS Lambdaでライブラリを動かす場合は、ローカル環境でライブラリをzipにパッケージ化してLambda Layerにアップロードする必要があります。ただし、このパッケージ化する環境によっては、Lambda側の環境と異なるアーキテクチャになることがあり、それが原因でエラーになることがあります。
例えば、私のローカルマシンをuname -a
すると以下のように表示されます。
Darwin xxxxxxMBP 21.6.0 Darwin Kernel Version 21.6.0: Mon Aug 22 20:19:52 PDT 2022; root:xnu-8020.140.49~2/RELEASE_ARM64_T6000 arm64
arm64とありますね。
そして、原因はまさしくここにありました。
Lambdaでは、アーキテクチャの選択肢としてarm64とx86_64が選べます。
ここでx86_64を選択したLambdaに、arm64でパッケージ化したzipをアップロードすると冒頭の以下のエラーになりました。
[ERROR] Runtime.ImportModuleError: Unable to import module 'app.main': No module named 'pydantic_core._pydantic_core'
これは、AWS Lambda関数がx86_64アーキテクチャで設定されておりarm64用のバイナリは互換性がないため、モジュールが見つからないエラーが発生しているのです。
解決方法
ネットを調べていると、dockerfileを利用する方法、Cloudshellの環境を利用する方法、アプリと同階層にpython
ディレクトリで配置する方法など、色々ありました。
ただ、私はいずれも成功できなかった(or正しく試せていない)ので、あくまで私のケースでは解決できた方法を紹介します。
それがAWS公式ドキュメントにも記載のある以下のスクリプトです。
(参考:以下の記事でも同様に対処している)
mkdir python
pip install \
--platform manylinux2014_aarch64 \
--target=python/python/lib/python3.12/site-packages/ \
--implementation cp \
--python-version 3.12 \
--only-binary=:all: \
--upgrade \
--no-deps \
-r requirements.txt
cd python
zip -r ../fastapi-layer.zip .
cd ..
rm -rf python
AWSドキュメントから一部変更してあります。
--only-binary=:all: --upgrade
だと、mysqlclientインストール時に以下のエラーのなりました。
ERROR: Could not find a version that satisfies the requirement mysqlclient (from versions: none) ERROR: No matching distribution found for mysqlclient
mysqlclientは特定のplatform用に事前にコンパイルされたバイナリが必要らしく、上記スクリプトのように少し改変したのはそのための処置です。
--no-deps
オプションを指定すると、依存関係を無視して指定されたパッケージのみをインストールできました。
--no-deps
Don’t install package dependencies.
私上記のようにインストールの上、Lambda側もarm64にしてアップロードすると正常に動作するようになりました。