![HW Raspberry Pi 4 Model B Rev 1.4](https://img.shields.io/badge/HW-Raspberry Pi 4 Model B Rev 1.4-brightgreen) ![OS-Ubuntu 20.04.1 LTS](https://img.shields.io/badge/OS-Ubuntu 20.04.1 LTS-brightgreen)
はじめに
PythonでGoogle Photos APIを叩こうと思ってネットを調べていたところ、google-api-python-clientのバージョンが2になっていたため上手く動かずに時間を使ってしまったので、記事投稿時点で動くコードを上げておく。
事前にGoogle Photos APIを有効化し、OAuth 2.0 Clientを作成してclient_secret.jsonを取得しておく必要がありますが、ここでは割愛します。
エラー
下記のようなコードでphotoslibraryを叩こうとすると、
buildのところでコケる。
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
SCOPES = ["https://www.googleapis.com/auth/photoslibrary"]
API_SERVICE_NAME = "photoslibrary"
API_VERSION = 'v1'
CLIENT_SECRET_FILE = './secret/client_secret.json'
creds = InstalledAppFlow.from_client_secrets_file(
CLIENT_SECRET_FILE, SCOPES).run_local_server()
with build(API_SERVICE_NAME, API_VERSION, credentials=creds) as service:
print(service.albums().list(pageSize=50).execute())
何やらこんなAPIは知らんと怒られた。
Google Photos Libraryはgoogle-api-python-clientで定義されていないようだ。
googleapiclient.errors.UnknownApiNameOrVersion: name: photoslibrary version: v1
結論
version 2.0.0以降は、指定しない場合デフォルトでライブラリ内を見るように変更されていた。GooglePhotosLibraryはローカルでは見つからないので、インターネット経由でDiscoveryかけるようにbuild時にstatic_discovery=Falseを指定してあげればよい。
下記はGoogle Photos APIを叩いてアルバムのリストを取得して表示するサンプル。
import pickle
from pathlib import Path
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
SCOPES = ["https://www.googleapis.com/auth/photoslibrary"]
API_SERVICE_NAME = "photoslibrary"
API_VERSION = 'v1'
CLIENT_SECRET_FILE = './secret/client_secret.json'
TOKEN_PICKLE = "./secret/token.pickle"
def get_authenticated_service() -> object:
if Path(TOKEN_PICKLE).exists():
# TOKENファイルを読み込み
with open(TOKEN_PICKLE, "rb") as token:
creds = pickle.load(token)
if creds.valid:
return creds
if creds and creds.expired and creds.refresh_token:
# TOKENをリフレッシュ
creds.refresh(Request())
else:
# TOKENファイルがないので認証フローを起動する(Default: host=localhost, port=8080)
creds = InstalledAppFlow.from_client_secrets_file(
CLIENT_SECRET_FILE, SCOPES).run_local_server()
# CredentialをTOKENファイルとして保存
with open(TOKEN_PICKLE, 'wb') as token:
pickle.dump(creds, token)
return creds
def main():
with build(API_SERVICE_NAME, API_VERSION, credentials=get_authenticated_service(), static_discovery=False) as service:
print(service.albums().list(pageSize=50).execute())
if __name__ == "__main__":
main()
google-api-python-clientのv1系とv2系の違い
MigrationGuideにBraking Changeとして明記されている。
下記は該当箇所の抜粋
v1系
from googleapiclient.discovery import build
# Retrieve discovery artifacts from the internet
with build('drive', 'v3') as service:
v2系
from googleapiclient.discovery import build
# Retrieve discovery artifacts from the client library
with build('drive', 'v3') as service:
# ...
# Retrieve discovery artifacts from the internet
with build('drive', 'v3', static_discovery=False) as service:
# ...