はじめに
この記事では、PythonでGoogleドライブを操作するパッケージの中からPyDrive2
(GitHub)を取り上げます。
GoogleドライブはDrive APIを介して操作できますが、PyDrive2
におけるDrive APIの認証部分について備忘録としてまとめます。
具体的には以下を扱います。
- 認証情報(OAuth 2.0 クライアント ID)をGCPコンソールで作る方法
- PyDrive2で認証する方法
- 認証情報をローカル端末に保存し、都度ブラウザの認証画面が立ち上がらないようにする方法
PyDrive2について
PythonでGoogleドライブを操作するパッケージとしてPyDrive
(GitHub)は多少知られているかもしれません。
残念ながら、PyDriveは1年以上前から更新が止まっています。
PyDriveからPyDrive2がフォークされたのが最近(2020年1月)のようです。
PyDrive2は「Maintained fork of PyDrive.」と謳っています。
PyDrive2では、後方互換性のない変更はまだ取り込まれていないようです(2020年5月時点)。
PyDrive2のドキュメントとして、PyDriveのドキュメントがリンクされているほどです。
また、PyDriveのIssueに蓄積された知見は、PyDrive2でもそのまま適用できる印象です。
動作環境
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.14.6
BuildVersion: 18G3020
$ python -V
Python 3.8.1
$ pip list | grep PyDrive2
PyDrive2 1.4.10
PyDrive2 使い出し
PyDriveのドキュメントの Quickstart に沿って進めます。
- Drive APIの操作に必要な認証情報をGCPコンソールで作成
- 作成した認証情報を使った認証
の順で進めます。
1. GCPコンソールから認証情報を作る
GCP (Google Cloud Platform)のアカウントがあり、GCPに1つ以上のプロジェクトを持っている状態を前提とします。
Quickstartに沿って、「OAuthクライアントID」を作っていきます。
- 有効化していない場合、GCPコンソールからDrive APIを有効化
- https://console.cloud.google.com/apis/api/drive.googleapis.com/overview にて行う
- この記事では「Drive-Template-Copy」プロジェクトでDrive APIを有効にし、OAuthクライアントIDを作成しています
- OAuthクライアントIDを作成(ドキュメントの値を入力)
- APIとサービス ダッシュボードからの操作をオススメ
- 左側のナビゲーションの「認証情報」から作成していく
- 作成後、開発端末に認証情報をダウンロード
2. 動作確認
Quickstartを参考に、以下のコードを動かします。
from pydrive2.auth import GoogleAuth # Quickstartからpydriveをpydrive2に読み替えます
gauth = GoogleAuth()
gauth.LocalWebserverAuth()
.
├── client_secrets.json
└── quickstart.py
quickstart.py
を実行するとブラウザが起動します。
$ python quickstart.py
Your browser has been opened to visit:
https://accounts.google.com/o/oauth2/auth?client_id=...
コマンドラインにも認証成功の旨が表示されています!
$ python quickstart.py
Your browser has been opened to visit:
:
Authentication successful.
毎回ブラウザが起動しないようにしたい
PyDriveのドキュメント OAuth made easy に進みます。
使い出しではわずか2行のコードでDrive APIを使うための認証が済みました。
とても簡単ですが、このスクリプトを実行するたびに毎回ブラウザからログインする必要があります。
これはスクリプトを使った自動化には向きません。
そこで認証に使った情報を保存し、以降は自動で更新するようにPyDrive2を設定していきます。
一度ログインしたあとは、保存した認証情報が更新して使われるので、ブラウザからのログインが不要になります。
上記を実現するために、settings.yaml
を書きます。
認証情報をファイルに保存する設定は以下のようになります。
# OAuth 2.0 クライアントの認証情報を指定(renameしています)
client_config_file: my_client_secrets.json
# 認証情報をファイルに保存する設定
save_credentials: True
save_credentials_backend: file
save_credentials_file: saved_credentials.json
# 認証情報(credentials)を自動で更新する設定(ブラウザが立ち上がらなくなる)
get_refresh_token: True
.
├── my_client_secrets.json
├── quickstart.py
└── settings.yaml
コマンドラインで python quickstart.py
を実行すると、初回はブラウザからログインが必要になります。
Drive APIを使った操作の範囲(スコープ ※後述)によって警告ページが表示されます。
「詳細を表示」して移動します。
※初めてアクセスする場合は。「Googleドライブのすべてのファイルの表示、編集、作成、削除」を許可するか確認するポップアップが出ました。
ポップアップで許可したあと、以下の画面になります。
許可するとブラウザに「The authentication flow has completed」と表示されるでしょう。
ブラウザを使った認証は初回のみです。
get_refresh_token
を有効にしている1ので、2回目以降は自動で認証情報を更新して認証するため、ブラウザは起動しません2。
.
├── my_client_secrets.json
├── quickstart.py
├── saved_credentials.json # 作成された。以降は自動で更新される
└── settings.yaml
補足事項
Drive APIのスコープ
settings.yaml
にはoauth_scope
という項目があります3。
今回は指定していないので、デフォルト値の [‘https://www.googleapis.com/auth/drive‘]
となります。
Drive APIのスコープ一覧によると、これはRestricted
なスコープです。
Restrictedなスコープを要求するアプリでGoogleの確認プロセスを通過していないアプリは「Unverified app(確認されていないアプリ)」として、先の「このアプリは確認されていません」というページが表示されます4。
https://support.google.com/cloud/answer/7454865 によれば、「OAuth同意画面(OAuth consent screen)」に https://www.googleapis.com/auth/drive
を追加する必要があります。
しかし、単に追加するだけでは不十分で、Googleのverification(確認)を申請する必要がありました。
PythonでGoogleドライブを操作して実現したいことは、今の段階では、個人的な自動化です。
第三者が使うアプリを開発するわけではないので、承認プロセスには進まず、このまま開発していく考えです5。
LocalWebserverAuth
とCommandLineAuth
初回のログインもブラウザが立ち上がらないようにするために、LocalWebserverAuth
をCommandLineAuth
に変えたところ、うまくいきませんでした。
ブラウザに表示された「承認エラー」から、OAuth クライアントIDをウェブアプリケーションとして作っているので、CommandLineAuth
には対応していないようです。
そのため、初回のブラウザでのログインは必須と考えています6。
settings.yamlとclient_secrets.json
settings.yamlとclient_secrets.jsonが、quickstart.pyと同じディレクトリにある場合、settings.yamlが読み込まれるようです。
気になったので、auth.py
のGoogleAuth
の実装を見てみました。
-
GoogleAuth()
という呼び出しで、"settings.yaml"
(デフォルト値)が指定されたことになる- settings.yamlをrenameした場合は、
GoogleAuth
の引数に渡せばよさそう
- settings.yamlをrenameした場合は、
-
GoogleAuth()
を実行する中で、settings.yamlが読み込まれる- settings.yamlに指定された
client_config_file
が使われる - settings.yamlに指定がない場合は、デフォルト値として
"client_secrets.json"
が使われる
- settings.yamlに指定された
この記事では
- settings.yamlを作る前はclient_secrets.jsonが使われ
- settings.yamlを作ったあとは、そこに指定された
client_config_file
が使われて
いますね。
-
get_refresh_token
の値を変更するたびに、初回はブラウザでログインする必要があるようです。保存された認証情報を削除して再実行するのをおすすめします(過去にsaved_credentials.json
がある状態で、get_refresh_token
を有効化したところ、反映されずにハマりました。「認証で返されるデータの項目が異なるのかな」と思っています) ↩ -
期間があくと認証情報を自動で更新できないことがあるようです。久しぶりに触ったところ、エラーが発生しました。保存された認証情報(
saved_credentials.json
)を削除して再実行して解決しました。 ↩ -
https://gsuitedevs.github.io/PyDrive/docs/build/html/oauth.html#automatic-and-custom-authentication-with-settings-yaml ↩
-
https://support.google.com/cloud/answer/7454865 より。「An unverified app is an app or Apps Script that requests a sensitive or restricted OAuth scope, but hasn't gone through the Google verification process」 ↩
-
「Apps in development: if your app is experimental or a test build, you don't need to go through verification unless you decide to launch it to the public.」https://support.google.com/cloud/answer/7454865 より ↩
-
ブラウザが起動できない実行環境では、保存した認証情報を複製して配置しています(ブラウザが立ち上がらないので問題なく実行できています) ↩