AWS Lambda, Python: pipenv 仮想環境の deploy package を作成する
pipenv で作成した仮想環境のライブラリを deploy package(.zip ファイル)に取り込む方法を解説する.Docker 使うと楽らしいけど,筆者が使えないのでそれに関することは書けなかった.Docker に関する情報を求めてた人はごめんなさい.
(アイキャッチは AWS Lambda Python Development Package on Ubuntu 18.04 より引用)
前提
- 実行環境:macOS Mojave 10.14.6
- Python 3.7 系(3.7.3)
- pipenv version 2018.11.26
- .venv(仮想環境)をプロジェクトディレクトリ下に作っていること(以下の記事を参照)
注意
(投稿直前に急ぎで追加した項のため雑な内容になっている.)
調べている途中に,本記事の内容が良くなさそうな気がしたのでこの「注意」の項を急遽追加.
本記事では,手動で deploy package を作る方法を紹介している.しかし,記事を書いている途中に,yaml ファイルと requirements.txt
を作ってコマンドを実行するだけで AWS Lambda(or S3)への zip ファイル(deploy package)のアップロードを自動化できるライブラリを見つけた.以下の(私の)ツイートの内容のリンクを参照.
Python-Lambda: The Essential Library for AWS Cloud Functions
— mathnuko (@mathnuko) August 4, 2019
Python 仮想環境(pipenv, virtualenv)から簡単に AWS Lambda に deploy できる Python ライブラリ.yaml と requirements.txt だけで Lambda に deploy package をアップロードできる.S3 にも対応.#memohttps://t.co/8dFHY3xxcH
もう一つ参考になりそうな記事を見つけた.serverless-framework(Python 用プラグインとして serverless-python-requirements がある) という npm で配布されているパッケージで,デプロイ自動化,デプロイパッケージ容量を削減できる機能がある.こちらも yaml ファイルと requirements.txt
で zip をアップロードできる.
自動化できる部分は自動化した方が良いので,本記事の手動で deploy package を作る方法は非効率だと思われる.上記の記事を参考にすることを勧める.本記事は供養目的である(ほぼ書き終わりだったため...).筆者は上記リンク先のツールに乗り換える予定.いずれこの記事も編集する(かもしれない).
以上を踏まえた上で本記事を読み進めて欲しい.
導入
AWS Lambda に Python の関数を登録するためには,関数が書かれたスクリプト,外部ライブラリを含めた .zip ファイルをアップロードする必要がある(標準ライブラリは必要ない).「外部ライブラリを含める」というのが注意点で,これは pip(env) install
でインストールしたライブラリ例えば requests や numpy などのライブラリがこれに該当する.
AWS Lambda 経由で API を叩いたり,数値計算を動かしたりなど,少し複雑なことをしたい場合には必ずライブラリが必須である.公式では zip ファイルの作り方を含めた,以下 2 つのアップロード方法が紹介されている.
pip install --target
でローカルディレクトリにライブラリをインストール -> そのディレクトリごと zip 化 -> アップロード- virtualenv で作った仮想環境の
site-packages
(インストールしたライブラリが保存されているディレクトリ) を zip 化 -> アップロード
本記事では,公式に無い pipenv で作った仮想環境のライブラリを含めた zip ファイルの作り方を解説する.
中身としては,「.venv
の site-package
を AWS Lambda にアップロードする .zip ファイルに含める」だけであり,公式の virtualenv での方法とほぼ変わりがないが(site-package
の場所が違うだけ?),覚書として残しておく.
pipenv 仮想環境のライブラリを zip 化
プロジェクトルートに移動し,.venv
ディレクトリの存在を確認.
$ cd [プロジェクトルート] $ ls -la | grep .venv # drwxr-xr-x 9 user-name staff 288 8 3 22:39 .venv
.venv
の site-package
を zip 化
- zip 化 UNIX コマンド:
zip -r [archive-name] [target-directory]
(拡張子.zip
は勝手につけてくれる.自分でつけても良い.-r
は再帰オプション.)
以下,プロジェクトルート下で実行するシェルスクリプト.
zip_lambda_function.sh
#!/bin/bash # pipenv 仮想環境を起動してから実行する PROJECT_DIR=$(pwd) SITE_PACKAGES_DIR=$(pipenv --venv)/lib/python3.7/site-packages echo "Project Location: $PROJECT_DIR" echo "Library Location: $SITE_PACKAGES_DIR" # to zip site-packages cd $SITE_PACKAGES_DIR rm -rf __pycache__ # your option 容量節約のため. zip -r $PROJECT_DIR/lambda.zip * # add lambda-function script(.py) cd $PROJECT_DIR zip -g lambda.zip lambda_function.py # zip に Python スクリプトを追加 # display zip file ls | grep *.zip
手順はとても単純.
- pipenv 仮想環境の
site-packages
ディレクトリを zip 化(lambda.zip
) - AWS Lambda に登録する関数が書かれた Python スクリプト(
lambda_function.py
)を zip に追加
※ ファイル名は分かりやすいように lambda という名前を使っているが自由に設定して良い.
Python スクリプトを機能ごとにモジュール化している場合は,zip -g lambda.zip *.py
のようにワイルドカード *
を使って Python スクリプトを全て zip に追加すれば良い(自作パッケージの場合は手動でパッケージディレクトリごと追加すれば良いと思う).
以上のシェルスクリプトを pipenv 仮想環境を起動させてから実行する.
$ cd [プロジェクトルート] $ pipenv shell # 仮想環境の起動 (virtual-environment-name) bash-3.2$ sh zip_lambda_function.sh # lambda.zip
プロジェクトルート下に AWS Lambda にアップロードするための zip ファイルが作られている.
zip ファイルを AWS Lambda にアップロード
最後に作成した zip ファイルを AWS Lambda にアップロードする.これに関してはネットに腐る程情報があるため各自でググり推奨(書くのがめんどい).参考になりそうな記事を貼っておく.
- 公式:zip のアップロード方法(冒頭に貼ったのと同じ)
- 公式:AWS Lambda の制限
本記事で問題になるのは,リンク先の「/tmp ディレクトリのストレージ」,「デプロイパッケージサイズ」の欄.前者はライブラリ,スクリプトなど全てを含めた上での AWS Lambda の最大容量(512 MB 以下)を表す.後者について,zip を直接アップロードする場合に 50 MB 以下という制限があるため注意が必要.
- デプロイパッケージが容量オーバーの場合の対処法
numpy, pandas, sklearn など数値計算系のライブラリを zip 化すると 50 MB を超えてしまう.この場合,冒頭で紹介した serverless-framework を使って圧縮してデプロイするか,S3 に 512 MB 以下の zip ファイルを置き,関数実行時に解凍・展開してライブラリを使用するという 2 つの方法がある.後者の方法では,ライブラリを AWS Lambda のストレージ /tmp
下に展開するため,展開後の容量が 512 MB 以下という制限を守る必要があるため注意.以下が参考になる.