Python用Google APIクライアントライブラリのImportエラーが発生してしまう問題をなんとかする
データアナリティクス事業本部@札幌の佐藤です。
突然ですが皆さんは『アイカツオンパレード!』はご覧になっているでしょうか。
『アイカツオンパレード!』はアイカツ!シリーズの歴代メインキャラクターだけではなくゲストキャラまで大集合するお祭りアニメです。
今までのダンスCGもたくさん出てくるので、毎週土曜日10時30分からテンションが上がります。
最終回が3月28日なのでぜひご覧ください。
また突然ですが、公式YouTube「アイチューブ」にて『アイカツオンパレード!ドリームストーリー』が3月28日から放送されることはご存じでしょうか。
『アイカツオンパレード!』の特別編として配信されます。
舞台がドリームアカデミーになっており、主人公が音城ノエルということで往年のアイカツ!ファンの方には吉報だったと思います。
アニメがテレビからYoutubeに移り変わったということもあり、どれだけ視聴されたのかが数字として見えるようになりました。
再生回数がどのくらいになるか個人的に興味があるため、AWS Lambdaを使用してYoutubeの再生回数を自動で取得できるようにしたいなと思っています。
ということで今回はAWS LambdaからYoutubeの再生回数を取得する実装で詰まった、google-api-python-client
のimportエラーについて書いていきたいと思います。
遭遇した事象
以下のようにbuild() 関数を実行した際に、ModuleNotFoundError
やImportError
が出力されてしまう状況です。
from apiclient.discovery import build def lambda_handler(event, context): YOUTUBE_API_KEY = 'Google Cloud PlatformサービスのAPIキー' youtube = build('youtube', 'v3', developerKey=YOUTUBE_API_KEY)
google-api-python-clientライブラリのアップロードまで
YoutubeにアクセスするためにPython用Google APIクライアントライブラリを使用します。
ただLambdaにはPython用Google APIクライアントライブラリはデフォルトで入っていないため、別途ライブラリを使えるようにする必要があります。
ローカルPCにディレクトリを作成して、以下コマンドで保存しておきます。
pip install --target ./python requests google-api-python-client google-auth requests-oauthlib
このフォルダをZIPファイル化します。
ただ、このZIPファイルは6MBくらいあるので、関数コードの「コードエントリタイプからアップロード」からアップロードすると
Lambda関数「XXXX」のデプロイパッケージが大きすぎて、インラインコード編集を有効にできません。ただし、関数を呼び出すことはできます。
というようなメッセージが出力されて、「コードをインラインで編集」が非表示になってしまいます。
ソース量もそんなに多くなくインライン編集したかったので、AWS LambdaのLayer機能からアップロードしました。
このような感じになっています。
実行時のエラー
動作チェックとして上記実装を行い、YouTube Data APIを使えるようにできるところまで実装しています。
この状況でボタン「テスト」を押下してエラーにならないかチェックしてみます。
正常終了しているようですが、ログ上エラーになっています。
出力されているログは以下になります。
Response: null Request ID: "df60528a-90cf-4b50-a14c-XXXXXXXXX" Function Logs: START RequestId: df60528a-90cf-4b50-a14c-XXXXXXXXXVersion: $LATEST [WARNING] 2020-03-26T06:07:01.330Z df60528a-90cf-4b50-a14c-XXXXXXXXX file_cache is unavailable when using oauth2client >= 4.0.0 or google-auth Traceback (most recent call last): File "/opt/python/googleapiclient/discovery_cache/__init__.py", line 36, in autodetect from google.appengine.api import memcache ModuleNotFoundError: No module named 'google.appengine' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/opt/python/googleapiclient/discovery_cache/file_cache.py", line 33, in <module> from oauth2client.contrib.locked_file import LockedFile ModuleNotFoundError: No module named 'oauth2client' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/opt/python/googleapiclient/discovery_cache/file_cache.py", line 37, in <module> from oauth2client.locked_file import LockedFile ModuleNotFoundError: No module named 'oauth2client' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/opt/python/googleapiclient/discovery_cache/__init__.py", line 42, in autodetect from . import file_cache File "/opt/python/googleapiclient/discovery_cache/file_cache.py", line 40, in <module> raise ImportError( ImportError: file_cache is unavailable when using oauth2client >= 4.0.0 or google-authEND RequestId: df60528a-90cf-4b50-a14c-XXXXXXXXX REPORT RequestId: df60528a-90cf-4b50-a14c-XXXXXXXXX Duration: 654.89 ms Billed Duration: 700 ms Memory Size: 128 MB Max Memory Used: 67 MB Init Duration: 399.61 ms
ログを見る限りModuleNotFoundError
やImportError
が発生しているようです。
対処方法
原因を探していると、google-api-python-client
のgithub上に同様の内容についてissueが起票されていました。
ModuleNotFoundError: No module named 'google.appengine'
タイトルの通りの現象が発生しているので、同様事象だと思います。
内容を見る限りbuild関数にcache_discovery=False
をセットすることで回避できるようなので、試してみます。
from apiclient.discovery import build def lambda_handler(event, context): YOUTUBE_API_KEY = 'Google Cloud PlatformサービスのAPIキー' youtube = build('youtube', 'v3', developerKey=YOUTUBE_API_KEY, cache_discovery=False)
結果も正常終了、ログも先ほどのようなメッセージが出力されなくなったのを確認できました。
最後に
google-api-python-client
のgithub上でissueとしてopenの状態のため、修正後はこのような対応は不要になると思います。
それにしても『アイカツオンパレード!ドリームストーリー』楽しみですね。