概要
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
を無効化する
google-api-python-client
oauth2client
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
google-api-python-client
今回はCloud Buildからジョブリストを取得する実装にしていますが、他のサービスでもおkです。
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のバージョンチェックに引っかかる?みたいなので、無効化して回避すればよいみたいです。
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
を取得するようにしました。
google-api-python-client
oauth2client
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