エラーの内容
Lambda 関数をデプロイしてトリガーすると、CloudWatch Logs に即座に以下のエラーが表示されます:
[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'requests'
Traceback (most recent call last):
File "/var/task/lambda_function.py", line 1, in <module>
import requests
Lambda は最小限の実行環境で動作しており、サードパーティのパッケージはあらかじめインストールされていません。コード内で import requests、import pandas、またはPython標準ライブラリ以外のものを呼び出す場合、それらのパッケージを自分でデプロイに含める必要があります。boto3 にも組み込みバージョンがありますが、古い場合があります。特定のバージョンが必要な場合は、それも一緒にバンドルしてください。
なぜこのエラーが発生するのか
.zip ファイルをアップロードする場合でも、コンソールのインラインエディタを使用する場合でも、Lambda は明示的に含めたファイルしか認識しません。ローカルマシンとの接続はありません。pip でインストールしたパッケージは仮想環境の中に存在しており、デプロイの成果物には含まれていないため、Lambda はそれらの存在を知る術がありません。
解決策 1 — 依存関係をデプロイパッケージにバンドルする(最速)
最も手早い解決策:パッケージをプロジェクトフォルダに直接インストールし、すべてをまとめて zip にします。
ステップ 1 — クリーンなプロジェクトフォルダを作成する
mkdir my_lambda
cd my_lambda
ステップ 2 — 依存関係をプロジェクトフォルダにインストールする
pip install requests -t .
-t . フラグは、グローバルの Python 環境ではなく現在のディレクトリにインストールするよう pip に指示します。関数に必要なすべてのパッケージに対してこの操作を繰り返してください。requests==2.31.0 の場合、約 300KB のファイルがフォルダに直接展開されます。
ステップ 3 — 関数ファイルを追加する
# lambda_function.py
import requests
def lambda_handler(event, context):
response = requests.get("https://httpbin.org/get")
return {
"statusCode": response.status_code,
"body": response.text
}
ステップ 4 — すべてを zip にまとめる
zip -r function.zip .
重要な点:lambda_function.py はサブフォルダの中ではなく、zip のルートに配置されていなければなりません。Lambda はトップレベルでハンドラを探し、サブディレクトリは検索しません。
ステップ 5 — zip をデプロイする
aws lambda update-function-code \
--function-name my-function-name \
--zip-file fileb://function.zip
解決策 2 — Lambda レイヤーを使用する(再利用に適した方法)
requests と boto3 を使用する Lambda 関数が5つある場合、同じパッケージを5つの別々の zip にバンドルするのはスペースの無駄遣いであり、更新も煩雑になります。Lambda レイヤーを使えば、依存関係を一度だけパッケージ化し、必要な任意の関数にアタッチできます。各デプロイの zip を軽量(場合によっては 10KB 未満)に保ちながら、依存関係の更新を一元管理できます。
ステップ 1 — レイヤーのディレクトリ構造を作成する
Python レイヤーは特定のフォルダ構成に従う必要があります。Lambda は python/ 配下のパッケージを探します。それ以外の名前では読み込まれません。
mkdir -p layer/python
pip install requests -t layer/python/
ステップ 2 — レイヤーを zip にする
cd layer
zip -r ../requests_layer.zip python/
cd ..
ステップ 3 — レイヤーを AWS に公開する
aws lambda publish-layer-version \
--layer-name requests-layer \
--zip-file fileb://requests_layer.zip \
--compatible-runtimes python3.9 python3.10 python3.11
出力から LayerVersionArn をコピーしてください。arn:aws:lambda:us-east-1:123456789012:layer:requests-layer:1 のような形式になっています。次のステップで必要になります。
ステップ 4 — レイヤーを関数にアタッチする
aws lambda update-function-configuration \
--function-name my-function-name \
--layers arn:aws:lambda:us-east-1:123456789012:layer:requests-layer:1
ステップ 3 でコピーした ARN に置き換えてください。
ステップ 5 — 関数コードをデプロイする(依存関係のバンドルは不要)
# 関数ファイルだけを zip にする — パッケージは不要
zip function.zip lambda_function.py
aws lambda update-function-code \
--function-name my-function-name \
--zip-file fileb://function.zip
解決策 3 — AWS SAM または CDK を使用する(CI/CD パイプライン向け)
適切なデプロイパイプラインを持つチームプロジェクトに取り組んでいる場合は、手動での zip 化を完全にスキップできます。requirements.txt を追加するだけで、SAM が sam build 実行時に依存関係のバンドルを自動的に処理してくれます。
# requirements.txt
requests==2.31.0
# template.yaml(関連部分)
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: lambda_function.lambda_handler
Runtime: python3.11
CodeUri: ./src
Layers: [] # SAM が requirements.txt から自動的にインストールする
sam build
sam deploy
修正の確認
デプロイ後、関数を呼び出してレスポンスを確認します:
aws lambda invoke \
--function-name my-function-name \
--payload '{}' \
response.json
cat response.json
正常に実行されると以下が返されます:
{"statusCode": 200, "body": "{...}"}
まだ Runtime.ImportModuleError が表示される場合は、最新のログを直接ストリームで確認してください:
aws logs tail /aws/lambda/my-function-name --follow
再デプロイする前に、パッケージが実際に zip の中に含まれているか確認してください:
unzip -l function.zip | grep requests
アーカイブのルートに requests/__init__.py が表示されているはずです。この行が表示されない場合、パッケージは zip に含まれていません。
エラーが繰り返し発生する一般的なミス
- Python バージョンの不一致: Python 3.11 で
pip installを実行しながら Python 3.9 ランタイムにデプロイすると、numpyやcryptographyなどのコンパイル済みパッケージが壊れます。ローカルの Python バージョンを Lambda ランタイムと完全に一致させてください。 - 誤ったディレクトリへのインストール:
-t .なしでpip install requestsを実行すると、パッケージはプロジェクトフォルダではなくシステムの Python にインストールされます。そのため zip には含まれません。 - ネストされた zip 構造: 親ディレクトリから zip を作成すると
my_lambda/lambda_function.pyのような構造になります。Lambda はこの方法ではハンドラを見つけられません。zip を作成する前に必ずプロジェクトフォルダにcdしてください。 - レイヤーのフォルダ名の不一致: Python レイヤーのパッケージは zip 内の
python/配下に置かれなければなりません。他のフォルダ名を使用すると、Lambda はレイヤー全体を無視します。 - レイヤーのアタッチ忘れ: レイヤーを公開しても、自動的に関数に紐付けられるわけではありません。
update-function-configuration --layersのステップは必須です。見落としやすく、気づきにくいミスです。 - プラットフォーム固有のホイール: C 拡張を持つパッケージ(
numpyやPillowなど)は Amazon Linux 2 向けにコンパイルされている必要があります。対応する Docker コンテナ内でビルドしてください:docker run --rm -v $(pwd):/var/task public.ecr.aws/lambda/python:3.11 pip install requests -t /var/task/
クイックリファレンス — どの解決策を使うべきか
- 単一の関数、シンプルな依存関係:
pip install -t .でバンドルして zip にする。 - 依存関係を共有する複数の関数: Lambda レイヤーを使用する。
- CI/CD を使うチームプロジェクト:
requirements.txtと共に SAM または CDK を使用する。 - 大規模またはコンパイル済みパッケージ(numpy、pandas、Pillow): Lambda ランタイムに合わせた Docker でビルドする。

