AWS Lambdaで発生する psycopg2._psycopg の ImportModuleError を解決する方法

どうも、きっしゅです。

最近は AWS の Lambda で Python を使ってコード書いているのですが、Postgres に接続するための psycopg2 がなかなか上手くレイヤーに登録できず苦戦したので、今後のためにもメモしておこうと思い、記事にしました。

Docker が使える環境さえ整っていたらこの記事のコマンドのコピペで問題解消できると思います。

ネットで調べた感じだと、この問題に苦戦している人は多数いるみたいので、同じ問題に直面している人の参考になりますと幸いです。

大前提として今回は Lambda のレイヤーに登録して psycopg2 を使うことを想定しておりますので、その点ご認識おきください。

Lambdaで発生する psycopg2._psycopg の ImportError を解決する方法

AWS Lambda を実行した時に出力される下記のエラー、みなさんはもう見飽きたと思います。

[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'psycopg2._psycopg'

これは言葉の通り、psycopg2._psycopg が見つからないために発生しているエラーなのですが、ディレクトリを見直しても、再インストール&再度レイヤー登録しても同じエラーが発生したりします。

全く同じ手順で別のライブラリをインストールしたら上手く動くってこともあったりしてもうわけわからんってなっている人も少なくはないと思います。

調べた感じ解決方法はいくらかあるみたいなのですが、設定がめんどうだったり、手順がややこしいものも多いです。

色々試していたら細かい設定やソースコードを触ることなく問題が解消できたので、その方法を記載していきます。

問題を解消するための前提条件の確認

今回の方法は Docker を使います。なので Docker が使える環境が整っている必要があります。

Docker を使うための環境がまだ整っていない場合はまずはその環境と整えてください。

Ubuntu の場合はこちらを参考にすればインストールできます。

Mac の場合は Docker Desktop on Mac をインストールするだけです。

Windows の場合は Hyper-V を許可した上で Docker Desktop on Windows をインストールする必要があります。(Windows はちょっとめんどくさい。。。)

Docker は使いますが、今回に関してはコマンドを実行するだけなのでぶっちゃけ Docker の知識がなくても困りません。

psycopg2._psycopg を解消する方法

pip install するために必要なファイルとディレクトリを作成する

まずはローカル環境に任意のディレクトリを作成し、そこに移動します。

cd ~ && mkdir python-lib && cd python-lib

今回は python-lib ってディレクトリを作成しました。

ディレクトリに移動したら、pip install するライブラリを記載した requirements.txt を作成します。

今回インストールしたいのは psycopg2-binary なので下記のコマンドを実行します。

echo 'psycopg2-binary' > requirements.txt

実行したら念の為ファイルの中身を確認するため、下記のコマンドを実行します。

cat requirements.txt 

psycopg2-binary と表示されていたらそれでOKです。

pip でインストールできるライブラリには psycopg2psycopg2-binary がありますが、 psycopg2-binary を使ってください。

2つの違いを簡単に説明すると、psycopg2-binary は実行する際に外部ライブラリやコンパイラが必要なくスタンドアローンなパッケージとして作成されているものです。

psycopg2 自体はC言語のラッパーであるためCコンパイラが必要になります。

ローカル環境では個別にインストールすればいいのですが、今回は Lambda のレイヤーに登録するので必要最小限のものだけをインストールしたいので、バイナリーのものを選択してインストールします。

Docker を使ってpip install を実行する

ディレクトリやファイルの準備ができたらあとは Docker を使って pip install を実行します。

実行するコマンドは下記です。

docker run -v "$PWD":/var/task "lambci/lambda:build-python3.8" /bin/sh -c "pip install -r requirements.txt -t python/lib/python3.8/site-packages/; exit"

上記のコマンドの場合は Python3.8 を想定して実行しているので、Python3.8 以外で利用する場合は 3.8 の部分を任意のバージョンに変更してください。

上記のコマンドを箇条書きで簡単に説明すると下記の通りです。

  • AWS Lambda Python3.8 の Docker イメージを使って Docker を起動する。
  • Docker の起動時にカレントディレクトリ(自分が今いるディレクトリ)をマウントする。
  • マウントしたディレクトリに psycopg2-binary を pip install する。

まあこんな感じです。

今回は site-packages 配下にインストールしましたが、Lambda 的には python ディレクトリ配下であれば問題ないので、Lambda で複数のバージョンの Python を使う場合であれば Python バージョン下の site-packages にはインストールしない方がいいと思います。

インストールされたpsycopg2-binaryをzipしてレイヤー登録する

インストールが完了したらあとは Zip 化してレイヤー登録するだけです。

Zip 化コマンドは下記です。手順に沿っていたら自分がいるディレクトリに python って名前のディレクトリが作成されているのでそのままこのコマンドを実行して問題ありません。

zip -r psycopg2.zip python

これで zip 化は完了です。

あとは AWS コンソールにログインして Lambda を選択し、レイヤーの登録を実施してください。

これで問題は解消すると思います。

まとめ

いかがでしたでしょうか?

自分の場合はこれでサクッと解決しました。

psycopg2 は C言語をラッパーしているのでそれが何かしらの影響を及ぼしていたのだと思います。

Docker を使った理由は Lambda のランタイムと同じ環境でインストールするのが一番確実だと思ったからです。(pip は OS 依存はないと思うのであまり関係ないかもしれませんが、、)

みなさまの快適な開発ライフの役に立ちますと幸いです。

AWS Docker Python
きっしゅをフォローする
Ibukish Lab+

コメント

タイトルとURLをコピーしました