AWS Lambdaでレイヤー追加してもエラーが解決しないのはフォルダ名が問題だった

AWS

こんにちはますのです。

先日よりPythonで作成したプログラムコードをLambdaで動かそうと試みております。
【Python3】地震情報の取得&通知を定期的にSlackへ送る仕組みを作ってみた(コード公開)

「import requests」などで外部ライブラリをimportする際にエラーが出て詰まった箇所があるのでメモとなります。

AWS Lambda実装時に発生したエラー

今回追加したかった外部ライブラリはこの2つ。

import slackweb
import requests

プログラムを実行したところLambda上で以下のエラーが発生しました。

{"errorMessage": "Unable to import module 'lambda_function': No module named 'requests'", "errorType": "Runtime.ImportModuleError", "requestId": "0aaaaaaaa-dddd-4444-a777-63333333333", "stackTrace": [] }

そんなモジュール名は見つからないよ。ということでAWS Lambda上に作成する必要がありました。

ライブラリをLambdaレイヤーに作成する

調べたところAWSのナレッジセンターに記載がありました。

通常、このエラーは、Lambda 環境が Python コードで指定されたライブラリを見つけられない場合に表示されます。これは、Lambda がすべての Python ライブラリに事前にパッケージ化されているわけではないためです。

このエラーを解決するには、Lambda の Python コードで使用するライブラリを含めたデプロイパッケージまたは Lambda レイヤーを作成します。

※重要:Python 用にインポートするライブラリを /python フォルダ内に配置します。

Python で Lambda コードを実行すると「モジュールをインポートできません」というエラーが表示されるのですが、どうすれば解決できますか?

ざっくりやることの概要は以下の流れになります。

  1. Python環境を用意する
  2. 「python」というフォルダを作成する(超重要)
  3. 「pip install -t /python (ライブラリ名)」でpythonフォルダにライブラリをダウンロードする
  4. 「python」フォルダをzip化する
  5. zip化したpythonフォルダをAWS Lambdaの「レイヤー」に追加する
mkdir python
pip install -t /python requests
zip -r requests.zip python/

AWSLambdaのレイヤー追加に関する細かな手順は外部サイトにえいやです。

【Lambda】import requests が使えるようにする【python】

詰まった箇所:ライブラリを保存するディレクトリ名は決まっている

わたしは概要の「②pythonフォルダ」ではなく、任意のフォルダ名でやっていたためエラーが出ていました。

mkdir test
pip install -t /test requests
zip -r requests.zip python/

## Lambdaテスト実行結果は変わらず
"errorMessage": "Unable to import module 'lambda_function': No module named 'requests'",
"errorType": "Runtime.ImportModuleError",

AWS Lambdaの公式ドキュメントを探していたところ記載を見つけました。

Lambda ランタイムごとに、PATH 変数に /opt ディレクトリ内の特定のフォルダが含まれます。レイヤー .zip ファイルアーカイブに同じフォルダ構造を定義すると、関数コードはパスを指定しなくても、レイヤーコンテンツにアクセスできます。
・Python
– パス:python、python/lib/python3.9/site-packages
AWS Lambda:ライブラリの依存関係をレイヤーに含める

追加したレイヤーのzipファイルは、Lambda環境の「/opt」に展開される様子。
zipから解凍したフォルダが「python」となっていない場合はサポートされていないフォルダとなるため、読み込みされずエラーが発生したようです。

各 Lambda ランタイムのレイヤーパス

各ランタイム毎にパスが異なるようですね。

ランタイム パス
Node.js nodejs/node_modules
nodejs/node14/node_modules (NODE_PATH)
Python python
python/lib/python3.9/site-packages (サイトディレクトリ)
Java
java/lib (CLASSPATH)
Ruby ruby/gems/2.7.0 (GEM_PATH)
ruby/lib (RUBYLIB)

参考サイト

【Lambda】import requests が使えるようにする【python】

Python で Lambda コードを実行すると「モジュールをインポートできません」というエラーが表示されるのですが、どうすれば解決できますか?

AWS Lambda:ライブラリの依存関係をレイヤーに含める

AWS Lambda Layersでライブラリを共通化

最新情報をチェックしよう!