概要
Google Cloud FunctionsでPython(Beta)を利用して、他のGCPサービスを利用する場合、google-api-python-clientを利用するのが便利です。
googleapis / google-api-python-client
https://github.com/googleapis/google-api-python-client
ただし現状、ImportError
が発生するケースがあるので、その対応方法です。(2018/10/31時点)
発生するエラー
ImportError: file_cache is unavailable when using oauth2client >= 4.0.0 or google-auth
回避策: cache_discovery
を無効化する
requirements.txt
google-api-python-client oauth2client
main.py
from googleapiclient import discovery from httplib2 import Http from oauth2client.client import GoogleCredentials def check_discovery_error(request): # Cloud Functions環境から認証情報を取得する credentials = GoogleCredentials.get_application_default() cloudBuild = discovery.build( 'cloudbuild', 'v1', # Cloud Buildじゃなく、他のサービスでもおk http=credentials.authorize(Http()), cache_discovery=False)# cache_discovery=Falseしてエラーを回避する request = cloudBuild.projects().builds().list(projectId='[GCPのプロジェクトID]') response = request.execute() print(response)
再現してみる
前提
- GCPプロジェクトが利用可能
gcloud beta
が端末にインストール済みで利用可
実装の用意
> mkdir 任意のディレクトリ > cd 任意のディレクトリ > touch requirements.txt > touch main.py
requirements.txt
google-api-python-client
今回はCloud Buildからジョブリストを取得する実装にしていますが、他のサービスでもおkです。
main.py(回避前)
from googleapiclient import discovery def check_discovery_error(request): cloudBuild = discovery.build('cloudbuild', 'v1') request = cloudBuild.projects().builds().list(projectId='GCPのプロジェクトID') response = request.execute() print(response)
これをCloud Functionsにデプロイして実行します。
> gcloud beta functions deploy check_discovery_error \ --trigger-http \ --runtime=python37 > gcloud beta functions call check_discovery_error
実行すると、以下のようにエラーが出力されます。
ログ(一部抜粋)
> gcloud functions logs read check_discovery_error E from oauth2client.contrib.locked_file import LockedFile E ModuleNotFoundError: No module named 'oauth2client' E E During handling of the above exception, another exception occurred: E E Traceback (most recent call last): E File "/env/local/lib/python3.7/site-packages/googleapiclient/discovery_cache/file_cache.py", line 37, in <module> E from oauth2client.locked_fileimport LockedFile E ModuleNotFoundError: No module named 'oauth2client' E E During handling of the above exception, another exception occurred: E E Traceback (most recent call last): E File "/env/local/lib/python3.7/site-packages/googleapiclient/discovery_cache/__init__.py", line 41, in autodetect E from . import file_cache E File "/env/local/lib/python3.7/site-packages/googleapiclient/discovery_cache/file_cache.py", line 41, in <module> E 'file_cache is unavailable when using oauth2client >= 4.0.0 or google-auth') E ImportError: file_cache is unavailable when using oauth2client >= 4.0.0 or google-auth I URL being requested: GET https://www.googleapis.com/discovery/v1/apis/cloudbuild/v1/rest I URL being requested: GET https://cloudbuild.googleapis.com/v1/projects/[GCPのプロジェクトID]/builds?alt=json I {'builds': [{'id': (略) D Function execution took 138 ms, finished with status code: 200
原因
調べて見るとあちこちでissueが上がっていますが、いまのところ、根本的な解決はされてないようです。
file_cache is unavailable when using oauth2client >= 4.0.0
https://github.com/googleapis/google-api-python-client/issues/299
File caching for the oauth2client >= 4.0.0
https://github.com/googleapis/google-api-python-client/issues/325
回避策
issueのコメントに回避策がコメントされていました。ありがたや^^
cache_discovery
を無効化する
ライブラリのインポート時にキャッシュを利用すると、oauth2clientのバージョンチェックに引っかかる?みたいなので、無効化して回避すればよいみたいです。
https://github.com/googleapis/google-api-python-client/issues/299#issuecomment-268915510
It seems to be the better way to silence this error, if one does not care about the cache, is to simply specify cache_discovery=False when performing discovery.build() — this avoids the broken code path.
以下のコメントの実装方法を参考にしました。
https://github.com/googleapis/google-api-python-client/issues/299#issuecomment-427118293
discovery.build
は cache_discovery
パラメータ指定する場合、http
パラメータも指定する必要があったので、oauth2client
を用いてCredentials
を取得するようにしました。
requirements.txt
google-api-python-client oauth2client
main.py(対応版)
from googleapiclient import discovery from httplib2 import Http from oauth2client.client import GoogleCredentials def check_discovery_error(request): # Cloud Functions環境から認証情報を取得する credentials = GoogleCredentials.get_application_default() cloudBuild = discovery.build( 'cloudbuild', 'v1', # Cloud Buildじゃなく、他のサービスでもおk http=credentials.authorize(Http()), cache_discovery=False)# cache_discovery=Falseしてエラーを回避する request = cloudBuild.projects().builds().list(projectId='[GCPのプロジェクトID]') response = request.execute() print(response)
再びデプロイと実行して、エラー出力がなくなっていることが確認できました。
やったぜ。
一部抜粋
D Function execution started I URL being requested: GET https://www.googleapis.com/discovery/v1/apis/cloudbuild/v1/rest I URL being requested: GET https://cloudbuild.googleapis.com/v1/projects/[GCPのプロジェクトID]/builds?alt=json I {'builds': [{'id': (略) D Function execution took 2352 ms, finished with status code: 200
参考
file_cache is unavailable when using oauth2client >= 4.0.0
https://github.com/googleapis/google-api-python-client/issues/299
File caching for the oauth2client >= 4.0.0
https://github.com/googleapis/google-api-python-client/issues/325
Google Driveにpythonでデータを登録する & Siderを使ってチェックしてみる
https://qiita.com/akiko-pusu/items/f05a5dcba544e97c057c
[GoogleCloudPlatform] API Client Libraryを用いてGoogle Cloud APIを利用する
https://qiita.com/j-un/items/dc46b3b766a7afb4080c
元記事はこちら
「Google Cloud Functionsでgoogle-api-python-clientを利用してfile_cache is unavailableエラーになったときの対応方法」