Python用のGoogle API / GCPライブラリの状況 (2019年末)
(2019年末)
ここ数年でPython用ライブラリが少し整理されたようで、ちまたの記事は現在の状況に合っていないものが多い。最新っぽいやり方を整理しておく。
最後にGoogle PhotosのAPI (Photos Library API) を呼んでみたので、それについても末尾に書いておく。
oauth2client
はDeprecated
Web上ではoauth2client
を使っている記事がたくさん見つかるが、これは既にdeprecatedになっている。現在は以下のようになっている。
- Service Accountの認証や、Googleのトークンの扱いは、
google-auth
で実装されている。 - OAuth 2.0のフローを行う必要があるときはサードパーティ製の
oauthlib
などを使う(google-auth-oauthlib
というヘルパも用意されている)。
ライブラリの構成
GCP用も含めて、ほとんどのライブラリはここにある:
以下は(ほぼ)関係ない:
Google Cloud Platform (GCP) 関係
GCPの各サービスごとにパッケージgoogle-cloud-*
が用意されている (例えば google-cloud-storage
など) 。ちなみに、かつて存在したgoogle-cloud
というメタパッケージは、既にdeprecatedで空っぽになっている。
これらは以下のような綺麗な名前空間に収まっている。
import google.cloud.speech
- repo: https://github.com/googleapis/google-cloud-python
- doc: 各
google-cloud-*
ごとに個別に存在する。上のURLからたどれる。
各サービスで共通の部分はgoogle-api-core
, google-cloud-core
, google-resumable-media
などのパッケージとして抽出されている。これらは必要に応じて依存パッケージとしてインストールされるのであまり気にしなくていい。
Google’s Discovery-based API
google-api-python-client
- これはGoogleのサービス(Google Driveなど)のAPIを叩くための汎用ライブラリ。API定義をネットから取ってきて、APIを表現するオブジェクトを手元で動的に組みたてる仕組みになっている。
import googleapiclient
- repo: https://github.com/googleapis/google-api-python-client
- docs: https://github.com/googleapis/google-api-python-client/blob/master/docs/README.md
- docs: http://googleapis.github.io/google-api-python-client/docs/epy/index.html
ただしGCPを扱うときはこれを使うべきではない。「GCPについてはアクティブに開発されているGCP用のライブラリを使え」とのこと。
google-auth
認証周りを抜き出したもの。Service Accountの認証のほか、トークンのverifyなどもこれでできる。google-cloud-*
とgoogle-api-python-client
はこれに依存している。
google-auth:
- repo: https://github.com/googleapis/google-auth-library-python
- docs: https://google-auth.readthedocs.io/en/latest/
google-auth
には、ユーザクレデンシャルを取得する(=OAuth 2.0のフローを助ける)機能がない(oauth2client
にはあった)。アクセストークンを取得したければ、oauthlib
などをそのまま使うか、Googleが用意しているヘルパーgoogle-auth-oauthlib
を使う。
(もちろん、Webフロントエンドなどがある場合はブラウザ上でGoogle Sign-Inなどを使ってアクセストークンを取得すればいいので、サーバ側はトークンの検証だけすればいい。)
google-auth-oauthlib:
- repo: https://github.com/googleapis/google-auth-library-python-oauthlib
- docs: https://google-auth.readthedocs.io/en/latest/
認証方法
これはPython特有ではないけど…
Google Cloud Platformの認証の種類は以下の通り:
- Service Account - server-to-serverの通信には基本的にこれを使う。OAuth 2.0に基づいている(がOAuth 2.0そのものではない?)。
- OAuth 2 - ふつうのOAuth 2.0のフロー。ユーザの同意を得て、ユーザのデータにアクセスするためのトークンを取得するときに使う。
- API Key - APIキーによる認証。一部のAPIを使うときに必要。
Service Account
推奨される方法: クレデンシャルファイルを利用する。環境変数 GOOGLE_APPLICATION_CREDENTIALS
でクレデンシャルのjsonファイルのパスを指定しておけば、あとはライブラリが裏で勝手に認証を行ってくれる。
上記の通り、通常はライブラリに任せればいいのだけど、内部的には次のようなことをしている → クライアントの秘密鍵で要求用のJWTを署名して、それをエンドポイントに送信してアクセストークンを取得し、そのトークンでAPIを呼ぶ。(Pythonだと、google/auth/service_accounts.py
のrefresh()
あたりを追うとわかる)。
JWTの署名アルゴリズムにはRS256(256bit RSA暗号)が使われる。一部のAPIでは、上記のJWTそのものをそのままアクセストークンとして使うこともできる。
OAuth 2.0
Googleが提供しているGoogle Sign-In (Web (JS), Android, iOS, TV, etc.) などの認証ライブラリが使える場合はそれを使えばアクセストークンを取得できる。認証時に必要なスコープを要求すればいい。
上記で対応できない場合は、PlainなOAuth 2.0を使う(デスクトップアプリ、CLIツールなど)。
Pythonの場合は、PlainなOAuth 2.0フローを簡便に行うためのgoogle-auth-oauthlib
パッケージも用意されている。
実際にやってみる。
google-cloud-*
のほうは分かりにくいことは特にないので触れない。ここではgoogle-api-python-client
を使ってみる。
コマンドラインから自分のアカウントのGoogle Photosの写真を列挙してみることにした。
事前準備として、Google Cloud Consoleで適当なOAuth 2のクライアントIDを作っておく必要がある。
そして、コード自体は以下だけでOK。短い。
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
# Obtain an access token
flow = InstalledAppFlow.from_client_secrets_file(
'client_id.json',
scopes=['https://www.googleapis.com/auth/photoslibrary.readonly'])
credentials = flow.run_local_server()
# Call the Photos Library API
photos_service = build('photoslibrary', 'v1', credentials=credentials)
result = photos_service.mediaItems().list().execute()
print(result['mediaItems'])
実行するとブラウザが開いてGoogleの認証ページが表示される。デスクトップアプリやCLIのツールでアクセストークンを受け取るためのトリックとして、ローカルにWebサーバを立ててそこをOAuthフローのリダイレクト先にする、ということを行うのだが、その一連の処理はgoogle_auth_oauthlib
のInstalledAppFlow
がすべてやってくれる。