LoginSignup
14

More than 3 years have passed since last update.

PythonでGoogleドライブを操作するパッケージPyDrive2の認証まわり

Posted at

はじめに

この記事では、PythonでGoogleドライブを操作するパッケージの中からPyDrive2GitHub)を取り上げます。
GoogleドライブはDrive APIを介して操作できますが、PyDrive2におけるDrive APIの認証部分について備忘録としてまとめます。
具体的には以下を扱います。

  • 認証情報(OAuth 2.0 クライアント ID)をGCPコンソールで作る方法
  • PyDrive2で認証する方法
  • 認証情報をローカル端末に保存し、都度ブラウザの認証画面が立ち上がらないようにする方法

PyDrive2について

PythonでGoogleドライブを操作するパッケージとしてPyDriveGitHub)は多少知られているかもしれません。
残念ながら、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 に沿って進めます。

  1. Drive APIの操作に必要な認証情報をGCPコンソールで作成
  2. 作成した認証情報を使った認証

の順で進めます。

1. GCPコンソールから認証情報を作る

GCP (Google Cloud Platform)のアカウントがあり、GCPに1つ以上のプロジェクトを持っている状態を前提とします。
Quickstartに沿って、「OAuthクライアントID」を作っていきます。

  1. 有効化していない場合、GCPコンソールからDrive APIを有効化
  2. OAuthクライアントIDを作成(ドキュメントの値を入力)

    • APIとサービス ダッシュボードからの操作をオススメ
    • 左側のナビゲーションの「認証情報」から作成していく 1-create_oauth_client_id.png →Quickstartにある設定値を入力 2-fill_out_creation_form.png →作成できました(このポップアップは「OK」をクリックして閉じる) 3-complete_creation.png
  3. 作成後、開発端末に認証情報をダウンロード
    4-download_client_id.png

    • 認証情報は作業ディレクトリに移動し、client_secrets.jsonとrenameします

2. 動作確認

Quickstartを参考に、以下のコードを動かします。

quickstart.py
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=...

5-login_google.png

Googleアカウントを選択してログインすると、
6-authentication_completed.png

コマンドラインにも認証成功の旨が表示されています!

$ python quickstart.py
Your browser has been opened to visit:

  :

Authentication successful.

毎回ブラウザが起動しないようにしたい

PyDriveのドキュメント OAuth made easy に進みます。

使い出しではわずか2行のコードでDrive APIを使うための認証が済みました。
とても簡単ですが、このスクリプトを実行するたびに毎回ブラウザからログインする必要があります。
これはスクリプトを使った自動化には向きません。
そこで認証に使った情報を保存し、以降は自動で更新するようにPyDrive2を設定していきます。
一度ログインしたあとは、保存した認証情報が更新して使われるので、ブラウザからのログインが不要になります。

上記を実現するために、settings.yaml を書きます。
認証情報をファイルに保存する設定は以下のようになります。

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 を実行すると、初回はブラウザからログインが必要になります。
7-login_google-again.png

Drive APIを使った操作の範囲(スコープ ※後述)によって警告ページが表示されます。
「詳細を表示」して移動します。
8-unverified_page.png

※初めてアクセスする場合は。「Googleドライブのすべてのファイルの表示、編集、作成、削除」を許可するか確認するポップアップが出ました。
ポップアップで許可したあと、以下の画面になります。

9-allow_access_private_data.png

許可するとブラウザに「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

LocalWebserverAuthCommandLineAuth

初回のログインもブラウザが立ち上がらないようにするために、LocalWebserverAuthCommandLineAuthに変えたところ、うまくいきませんでした。

ブラウザに表示された「承認エラー」から、OAuth クライアントIDをウェブアプリケーションとして作っているので、CommandLineAuthには対応していないようです。

could_not_use_commandlineauth.png

そのため、初回のブラウザでのログインは必須と考えています6

settings.yamlとclient_secrets.json

settings.yamlとclient_secrets.jsonが、quickstart.pyと同じディレクトリにある場合、settings.yamlが読み込まれるようです。
気になったので、auth.pyGoogleAuth実装を見てみました。

  • GoogleAuth()という呼び出しで、"settings.yaml"(デフォルト値)が指定されたことになる
    • settings.yamlをrenameした場合は、GoogleAuthの引数に渡せばよさそう
  • GoogleAuth()を実行する中で、settings.yamlが読み込まれる
    • settings.yamlに指定されたclient_config_fileが使われる
    • settings.yamlに指定がない場合は、デフォルト値として "client_secrets.json" が使われる

この記事では

  • settings.yamlを作る前はclient_secrets.jsonが使われ
  • settings.yamlを作ったあとは、そこに指定されたclient_config_fileが使われて

いますね。


  1. get_refresh_tokenの値を変更するたびに、初回はブラウザでログインする必要があるようです。保存された認証情報を削除して再実行するのをおすすめします(過去にsaved_credentials.jsonがある状態で、get_refresh_tokenを有効化したところ、反映されずにハマりました。「認証で返されるデータの項目が異なるのかな」と思っています) 

  2. 期間があくと認証情報を自動で更新できないことがあるようです。久しぶりに触ったところ、エラーが発生しました。保存された認証情報(saved_credentials.json)を削除して再実行して解決しました。 

  3. https://gsuitedevs.github.io/PyDrive/docs/build/html/oauth.html#automatic-and-custom-authentication-with-settings-yaml 

  4. 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」 

  5. 「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 より 

  6. ブラウザが起動できない実行環境では、保存した認証情報を複製して配置しています(ブラウザが立ち上がらないので問題なく実行できています) 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14