LambdaでRuntime.ImportModuleErrorが発生した時の対処
Contents
概要
- 今回は、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が発生しました。