lambdaに外部モジュールを読み込ませる

AWS lambdaを使ってYahoo! Open Local Platform(YOLP)の気象情報APIをたたいて、気象情報を取ってこようとしたら以下のエラーが出て実行できなかった。

Unable to import module 'lambda_function': No module named 'requests'

コード

# ~/lambda_function.py
-----------------------

import json
import urllib
import requests
import re

def lambda_handler(event, context):

    APP_ID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    BASE_URL = "http://weather.olp.yahooapis.jp/v1/place"
    COORDINATES = "xxxxx,xxxxx"
    OUTPUT="json"

    Yahoo_URL = BASE_URL + "?appid=%s&coordinates=%s&output=%s" % (APP_ID,COORDINATES,OUTPUT)

    Weather_PARAMS = {
        "appid" : APP_ID,
        "coordinates" : COORDINATES,
        "output" : OUTPUT
    }

    weather = requests.get(Yahoo_URL,params=Weather_PARAMS).json()

エラー内容と原因

Unable to import module 'lambda_function': No module named 'requests'

どうやら外部モジュールのrequestsが読み込めなくてエラーが出力されていたようでした。

Lambdaに標準で同梱されているモジュール(aws-sdk, http,child_process等)以外を使いたい場合には、ローカルPC等でモジュールを含めたデプロイパッケージ(ZIPファイル)を作成しなければならないようです。

lambdaで外部モジュールを使用したことがなく、いつも通りにWebブラウザ上で関数の作成、編集を行なっていたためこのようなことが起こってしまいました。

対処法

今回はpipを使用してrequestsをローカルディレクトリにインストールし、デプロイパッケージを作成します。

  1.  依存関係のディレクトリを作成
~/$ mkdir package
  1. --targetオプションでライブラリをパッケージディレクトリにインストール
~/$ cd package
~/package$ pip install requests --target .
  1. ZIPアーカイブの作成
~/package$ zip -r9 ../function.zip .
  1. 関数コードをアーカイブに追加
~/package$ cd ../
~/$ zip -g function.zip lambda_function.py
  1. ZIPアーカイブをlambdaにアップロード

lambdaの管理コンソールに移動し、「コードエントリタイプ → .zipファイルをアップロード」でZIPファイルをアップロードします。

以上の手順を踏んだ後に、保存してテストをしたところ、実行できました。

参考

Python の AWS Lambda デプロイパッケージ