serverless frameworkで外部モジュールを利用したPythonのlambdaをデプロイする時は..

2 min読了の目安(約2300字TECH技術記事

serverless frameworkを使って、 Python で書いたスクリプトを AWS Lambda にデプロイしようとした際に詰まったのでメモ。

何が起こった?

serverless framework で deploy は成功するものの、lambda を実行すると外部モジュール の import エラーとなりました。

errorMessage": "Unable to import module 'handler': No module named 'BeautifulSoup'
errorType": "Runtime.ImportModuleError

もちろんローカルでは外部モジュールを pip インストールしているので、テストしても正常に動作します。

原因

Python で lambda に標準で同梱されているモジュール以外を利用する場合は、外部モジュールも明示的にデプロイする Zip ファイルに含める必要があるようです。
Serverless Framework で特に設定せずデプロイした場合、実行ファイルにて import している外部モジュールはデプロイ対象に含まれないのでエラーが発生していました。

https://docs.aws.amazon.com/lambda/latest/dg/python-package.html

対応

serverless-python-requirements を使って、依存する外部モジュールも一緒に Zip にまとめてデプロイするようにします。

https://github.com/UnitedIncome/serverless-python-requirements

以下コマンドで serverless-python-requirements のインストール(npm)と、package.jsonの作成、serverless.ymlの plugins への追記が完了します。

sls plugin install -n serverless-python-requirements

そして、pip で import した外部パッケージを requirements.txt にまとめます。

pip freeze > requirements.txt

これで準備は完了です。あとは通常のデプロイコマンドでデプロイすればエラーが解消されるはずです 🎉

sls deploy

補足

Pure Python以外の外部モジュールを使う場合

外部モジュールとして import しているものの内部で、C 言語を使っている場合など、Amazon Linux 環境でインストール(ビルド)したファイルを使ってパッケージングする必要があります。 Numpy、Scipy などです。
その場合は、通常のserverless-python-requirementsの設定ではエラーが発生してしまうのですが、Docker と docker-lambda イメージの設定を行うことで解消されます。

serverless.yml に以下を追記してください。

custom:
  pythonRequirements:
    dockerizePip: true

こちらは安定のクラスメソッドさんの記事を参考にさせて頂きました。

容量の大きい外部モジュールを使う場合

numpyscipyなどの容量の大きい外部モジュールを使う場合は、lambda のデプロイ容量制限に引っかかることがあります。
その場合の容量削減にもserverless-python-requirementsは対応しています。

serverless.yml に以下を追記してください。

custom:
  pythonRequirements:
    zip: true
    slim: true

そして、lambda の実行ファイルの先頭に以下を追記します。

try:
  import unzip_requirements
except ImportError:
  pass

参考