LoginSignup
4
3

More than 1 year has passed since last update.

AWS LambdaでPython向けLayerを作ろうとしたらはまった話

Posted at

AWS Lambda(Python)を使ってGoogle APIにアクセスしようとしたらライブラリではまった話です。
(Python初心者なので誤った記述があるかもしれません)

環境

  • 開発環境用にEC2 Amazon Linux2 + Python 3.7
  • Google APIにはサービスアカウントでアクセスする
  • Google API利用に必要なPythonパッケージ用にLambda Layerを作成する

参考にした記事

  • メインのコード自体は「補足:サービスアカウントを使ったやり方」を
    ほぼそのまま活用させていただきました。

  • 必要なパッケージについてはGoogleの「Python quickstart」を参照しています。

事象

pip -tでインストールしたディレクトリを圧縮・Layer化したのに、Lambdaが以下のエラーを吐く。

[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'google.oauth2' Traceback (most recent call last):

※Layer用のzipは以下の手順で作成(Layerの作り方は、いつもお世話になっているクラスメソッドさん記事参照)

layer.zip
$ mkdir python
$ pip3 install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib -t python/
$ zip -r layer.zip python/

切り分け

1. ローカルで同じようにパッケージをインストールしコードを動かしたときはエラーが出なかった
 →Layerの問題?

2. google.oauth2google-auth-oauthlibの前提パッケージ
 →一緒にインストールされているはず。

3. -tで指定したパッケージのインストール先にgoogle.oauth2が存在するかどうか
 →なぜかprotobufしか存在しない

$ ls python/google/
protobuf  _upb

4. ローカル(-t 指定なし)のパッケージインストール先を見てみる
 →oauth2はある。逆にprotobufが無い。(つまりprotobufは別のところにインストールされている?)

$ ls /usr/local/lib/python3.7/site-packages/google
api  api_core  auth  cloud  gapic  logging  longrunning  oauth2  rpc  type

5. protobufのインストール先を探す
 →/usr/local/lib/ ではなく /usr/local/lib64/ にインストールされている。
  /usr/local/lib64/を確認すると3と同じようにprotobufしか存在しない状態。

$ pip3 show protobuf
Name: protobuf
Version: 4.21.7
Summary: 
Home-page: https://developers.google.com/protocol-buffers/
Author: protobuf@googlegroups.com
Author-email: protobuf@googlegroups.com
License: 3-Clause BSD License
Location: /usr/local/lib64/python3.7/site-packages
Requires: 
Required-by: google-api-core, googleapis-common-protos
$ ls /usr/local/lib64/python3.7/site-packages/google/
protobuf  _upb

 
推測
-t を使うことでlib/ と lib64/ に分かれるはずのパッケージが同じディレクトリにインストールされてしまい、上書きされている?

原因

どうやら pip の --upgrade オプションと -t を併用した場合、同じ名前で異なるプラットフォーム(32bit と 64bit)のパッケージがあると追加ではなく、上書きされてしまうようです。
(upgradeだから他のパッケージには影響がないかと思いきや、ディレクトリが同じだと置き換えになる)

githubでも議論されていて、closedにはなっているもののズバリの解決策がありません。

You cannot pip install a single set of requirements that have mixed pure lib and platform lib installations with the same name, on a platform where the pure lib and platform lib folders are different, as pip will not merge these together.

--upgradeの説明を追加したほうがいいんじゃない?とも言われていますね。

- WARNING: Target directory /path/to/target/namespace already exists. Specify --upgrade to force replacement.
+ WARNING: Target directory /path/to/target/namespace already exists. Specify --upgrade to force replacement (existing 'namespace' will be replaced completely, not merged)

回避策

pip -tによるディレクトリ指定のインストールは利用できないので、pythonの仮想環境を利用し
Layer用zipファイルを作成することにします。

$ python3 -m venv env
$ source env/bin/activate
$ pip3 install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
$ cp -pr env/lib/python3.7/site-packages python
$ zip -r layer.zip python/

 
仮想環境は lib64/ が lib/へのシンボリックリンクになっており、パッケージが同じディレクトリに共存できます。
(googleディレクトリにprotobufと他のパッケージが存在している)

$ ls -l env/
total 8
drwxrwxr-x 2 ec2-user ec2-user 4096 Oct 17 16:41 bin
drwxrwxr-x 2 ec2-user ec2-user    6 Oct 17 16:41 include
drwxrwxr-x 3 ec2-user ec2-user   23 Oct 17 16:41 lib
lrwxrwxrwx 1 ec2-user ec2-user    3 Oct 17 16:41 lib64 -> lib
-rw-rw-r-- 1 ec2-user ec2-user   70 Oct 17 16:41 pyvenv.cfg

$ ls env/lib/python3.7/site-packages/google
api  api_core  auth  cloud  gapic  logging  longrunning  oauth2  protobuf  rpc  type  _upb

結果

仮想環境で作成したlayer.zipを読み込ませたところ、エラーなくGoogle APIが実行できるようになりました。

START RequestId: ee65c39b-6d0d-44b5-81e4-xxxxxxxxxx Version: $LATEST
Getting the upcoming 10 events
No upcoming events found.
{'kind': 'calendar#events', 'etag': '"xxxxxxxxxxxxxxx"', 'summary': 'Work', 'updated': '2022-10-18T01:11:51.814Z', 'timeZone': 'Asia/Tokyo', 'accessRole': 'reader', 'defaultReminders': [], 'nextSyncToken': '---------------------------------', 'items': []}
END RequestId: ee65c39b-6d0d-44b5-81e4-xxxxxxxxxx
REPORT RequestId: ee65c39b-6d0d-44b5-81e4-xxxxxxxxxx Duration: 3485.31 ms Billed Duration: 3486 ms Memory Size: 128 MB Max Memory Used: 87 MB Init Duration: 565.76 ms

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3