- 1. 概要
- 2. Runtime.ImportModuleErrorの対処方法
- 3. Lambda開発環境の構築方法
- 4. Lambdaにコードをデプロイする3つのポイント
— 4.1. ポイント1: デプロイパッケージの作成
— 4.2. ポイント2: Handler名を指定する
— 4.3. ポイント3: ランタイムのバージョンを指定する - 5. 参考資料
概要
- 今回は、LambdaでRuntime.ImportModuleErrorが発生した時の対処方法をまとめます。LambdaでImportに関する情報は典型的かもしれませんが、私の場合はインターネット上の情報だけではエラーを解決できず、調査に時間が掛かりました。今後の方のために、本記事にまとめたいと思います。
- 本記事では、先ずRuntime.ImportModuleErrorを対処するための3つのポイントを記載しております。
- そして、ベースとなるLambdaの開発環境構築からLambda関数にデプロイパッケージをデプロイするまでの手順をやさしく説明しております。開発環境は、EC2 に、Amazon Linux2のインスタンスを起動した環境です。言語はPython を使用します。Lambdaで開発を始めるエンジニアの参考にしてください。
Runtime.ImportModuleErrorの対処方法
- 今回、初めてLamndaに標準以外のライブラリを使用しました。後にご紹介する開発環境を構築し、デプロイパッケージを作成したにも関わらず、下記のエラーとなり、Lambdaが実行できません。
- [ERROR] Runtime.ImportModuleError: Unable to import module ‘lambda_function’: No module named ‘pyminizip’
- 以下に、Runtime.ImportModuleErrorの対処方法をまとめます。ポイント1、ポイント2はインターネット上の他資料にも記載がありましたが、今回はポイント3にハマっておりました。詳細は、後述のLambdaにコードをデプロイする3つのポイントを参照ください。
- ポイント1: 開発環境で、Lambdaで使用する(標準以外の)ライブラリを追加したデプロイパッケージ(ZIPファイル)を作成する。
- ポイント2: デプロイパッケージをアップロードした後、Handler名を指定する必要あり。Handler名は、「コードのファイル名.Handlerのメソッド名」とする。
- ポイント3: 開発環境に合わせて、ランタイムのバージョンを指定する必要あり。
Lambda開発環境の構築方法
- 今回は、Amazon Linux2のインスタンスに環境構築を行います。その他のMac、WSL(Windows Subsystem for Linux)+ Ubuntuでも環境構築は可能です(多少手順が変わります)。
- 今回、開発環境にAmazon Linux2を使用する理由は、Lambdaと同じAWSアカウント内に起動したAmazon Linux2を使用することで、IAMロールなどの環境依存の確認も合わせて行うことができるからです。
- 先ず、PythonでAWSリソースにアクセスするための、boto3ライブラリをインストールします。必須ではありませんが、事前準備としてpipのアップグレードを実施しています。rootでpythonを実行する場合は、必要に応じてsudo を付けてください。
$ pip install --upgrade pip $ pip install boto3 $ pip list Package Version --------------- -------- boto3 1.9.143 botocore 1.12.143 docutils 0.14 jmespath 0.9.4 pip 20.1 python-dateutil 2.8.0 pytz 2019.1 s3transfer 0.2.0 setuptools 39.0.1 six 1.12.0 urllib3 1.24.3
- 次に、この後の検証で使用するライブラリ(pyminizip)のインストールに必要なパッケージをインストールします。こちらは、sudoが必要ですね。
$ sudo yum install -y gcc zlib-devel $ yum list installed gcc zlib-devel
- 次は、使用したいライブラリ(pyminizip)をインストールします。こちらもrootでpythonを実行する場合は、必要に応じてsudo を付けてください。
$ pip install pyminizip Defaulting to user installation because normal site-packages is not writeable Collecting pyminizip Downloading pyminizip-0.2.4.tar.gz (258 kB) |????????????????????????????????| 258 kB 12.7 MB/s Could not build wheels for pyminizip, since package 'wheel' is not installed. Installing collected packages: pyminizip Running setup.py install for pyminizip ... Successfully installed pyminizip-0.2.4 $ pip list Package Version --------------- -------- boto3 1.9.143 botocore 1.12.143 docutils 0.14 jmespath 0.9.4 pip 20.1 pyminizip 0.2.4 python-dateutil 2.8.0 pytz 2019.1 s3transfer 0.2.0 setuptools 39.0.1 six 1.12.0 urllib3 1.24.3
- 私の場合は、Pythonのソースと同じカレントディレクトリにもライブラリをインストールします。次のステップで行うデプロイパッケージの作成に使用します。
$ cd work-dir $ pip install pyminizip --target . Collecting pyminizip Using cached pyminizip-0.2.4.tar.gz (258 kB) Could not build wheels for pyminizip, since package 'wheel' is not installed. Installing collected packages: pyminizip Running setup.py install for pyminizip ... Successfully installed pyminizip-0.2.4 $ ls lambda-s3-make-passwdzip.py pyminizip.cpython-36m-x86_64-linux-gnu.so pyminizip-0.2.4-py3.6.egg-info
Lambdaにコードをデプロイする3つのポイント
ポイント1: デプロイパッケージの作成
- 前述の環境構築の手順で、開発環境にLambdaで使用する標準以外のライブラリをインストールしたかと思います。開発したソースとカレントディレクトリにインストールしたライブラリをアーカイブしたデプロイパッケージを作成します。ここでのポイントは、上位のディレクトリをZIP圧縮するのではなく、カレントディレクトリ内のファイルのみをZIP圧縮することです。
- 念のため、unzip -l コマンドを使用し、ZIPファイルを展開せず中身を確認します。
$ cd work-dir/ $ zip -r ../lambda-s3-make-passwdzip.zip . adding: pyminizip.cpython-36m-x86_64-linux-gnu.so (deflated 62%) adding: pyminizip-0.2.4.dist-info/ (stored 0%) adding: pyminizip-0.2.4.dist-info/top_level.txt (stored 0%) adding: pyminizip-0.2.4.dist-info/WHEEL (deflated 3%) adding: pyminizip-0.2.4.dist-info/METADATA (deflated 61%) adding: pyminizip-0.2.4.dist-info/RECORD (deflated 35%) adding: pyminizip-0.2.4.dist-info/INSTALLER (stored 0%) adding: lambda-s3-make-passwdzip.py (deflated 50%) $ unzip -l ../lambda-s3-make-passwdzip.zip Archive: ../lambda-s3-make-passwdzip.zip Length Date Time Name --------- ---------- ----- ---- 439880 05-11-2020 00:46 pyminizip.cpython-36m-x86_64-linux-gnu.so 0 05-11-2020 00:46 pyminizip-0.2.4.dist-info/ 10 05-11-2020 00:46 pyminizip-0.2.4.dist-info/top_level.txt 104 05-11-2020 00:46 pyminizip-0.2.4.dist-info/WHEEL 2680 05-11-2020 00:46 pyminizip-0.2.4.dist-info/METADATA 502 05-11-2020 00:46 pyminizip-0.2.4.dist-info/RECORD 4 05-11-2020 00:46 pyminizip-0.2.4.dist-info/INSTALLER 1475 05-07-2020 21:33 lambda-s3-make-passwdzip.py --------- ------- 444655 8 files
- 出来たデプロイパッケージをLambda関数にアップロードします。10MBを超える場合は、S3 経由でアップロードが必要となります。
ポイント2: Handler名を指定する
- デプロイパッケージをアップロードした後、Handler名を指定する必要があります。Handler名は、「コードのファイル名.Handlerのメソッド名」となります。デフォルトのHandler名は、lambda_function.lambda_handlerですね。
ポイント3: ランタイムのバージョンを指定する
- 開発環境に合わせて、ランタイムのバージョンを指定する必要があります。今回、開発環境はPython 3.6 であり、ランタイムがPython 3.7 となっていたためRuntime.ImportModuleErrorが発生しました。
参考資料
Python の AWS Lambda デプロイパッケージ - AWS Lambda
デプロイパッケージは、関数のコードと依存関係を含む ZIP アーカイブです。Lambda API を使用して関数を管理する場合や、AWS SDK 以外のライブラリや依存関係を含める必要がある場合は、デプロイパッケージを作成する必要があります。パッケージを Lambda に直接アップロードするか、Amazon S3 バケットを使用して Lambda にアップロードすることができます。デプロイパッケージが 50 MB 以上の場合は、Amazon S3 を使用する必要があります。 Python 関数コードおよび依存関係のデプロイパッケージを作成するには、AWS SAM CLI の