Google Photos API + python: Working non-deprecated example

Question:

I’ve been finding such a mix of code examples. But nothing with a maintained library (google-auth) + full working example. google-api-python-client and oauth2client are no longer supported (https://github.com/googleapis/google-api-python-client/issues/651).

Here’s a working example with deprecated libraries, but I’d like to see some examples that allow full access to the api (searching by albumId currently doesn’t work with this library):

from apiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools

# Setup the Photo v1 API
SCOPES = 'https://www.googleapis.com/auth/photoslibrary.readonly'
store = file.Storage('credentials.json')
creds = store.get()
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
    creds = tools.run_flow(flow, store)
service = build('photoslibrary', 'v1', http=creds.authorize(Http()))

# Call the Photo v1 API
results = service.albums().list(
    pageSize=10, fields="nextPageToken,albums(id,title)").execute()
items = results.get('albums', [])
if not items:
    print('No albums found.')
else:
    print('Albums:')
    for item in items:
        print('{0} ({1})'.format(item['title'].encode('utf8'), item['id']))
Asked By: KFunk

||

Answers:

  • You want to use google_auth instead of oauth2client, because oauth2client is deprecated.
  • You have already been able to use Photo API.

If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.

For example, the sample script for authorizing can be seen at the Quickstart of Drive API with python. You can see the method for installing the library. Using this, your script can be modified as follows.

Modified script:

from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request


def main():
    credentialsFile = 'credentials.json'  # Please set the filename of credentials.json
    pickleFile = 'token.pickle'  # Please set the filename of pickle file.

    SCOPES = ['https://www.googleapis.com/auth/photoslibrary']
    creds = None
    if os.path.exists(pickleFile):
        with open(pickleFile, 'rb') as token:
            creds = pickle.load(token)
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                credentialsFile, SCOPES)
            creds = flow.run_local_server()
        with open(pickleFile, 'wb') as token:
            pickle.dump(creds, token)

    service = build('photoslibrary', 'v1', credentials=creds)

    # Call the Photo v1 API
    results = service.albums().list(
        pageSize=10, fields="nextPageToken,albums(id,title)").execute()
    items = results.get('albums', [])
    if not items:
        print('No albums found.')
    else:
        print('Albums:')
        for item in items:
            print('{0} ({1})'.format(item['title'].encode('utf8'), item['id']))


if __name__ == '__main__':
    main()
  • About the script for retrieving the album list, your script was used.
  • When you run this script, at first, the authorization process is run. So please authorize the scope. This process is required to run only one time. But if you want to change the scopes, please delete the pickle file and authorize again.

References:

If I misunderstood your question and this was not the direction you want, I apologize.

Added 1:

If you want to use the method of mediaItems.search, how about the following sample script? About the script for authorizing, please use above script.

Sample script:

service = build('photoslibrary', 'v1', credentials=creds)
albumId = '###'  # Please set the album ID.
results = service.mediaItems().search(body={'albumId': albumId}).execute()
print(results)

Added 2:

  • You want to remove googleapiclient from my proposed above sample script.
  • You want to retrieve the access token using google_auth_oauthlib.flow and google.auth.transport.requests.
  • You want to retrieve the media item list in the specific album using request of python without googleapiclient.

If my understanding is correct, how about this sample script?

Sample script:

Before you use this script, please set the variable of albumId.

from __future__ import print_function
import json
import pickle
import os.path
import requests
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request


def main():
    credentialsFile = 'credentials.json'
    pickleFile = 'token.pickle'

    SCOPES = ['https://www.googleapis.com/auth/photoslibrary.readonly']
    creds = None
    if os.path.exists(pickleFile):
        with open(pickleFile, 'rb') as token:
            creds = pickle.load(token)
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                credentialsFile, SCOPES)
            creds = flow.run_local_server()
        with open(pickleFile, 'wb') as token:
            pickle.dump(creds, token)

    albumId = '###'  # <--- Please set the album ID.

    url = 'https://photoslibrary.googleapis.com/v1/mediaItems:search'
    payload = {'albumId': albumId}
    headers = {
        'content-type': 'application/json',
        'Authorization': 'Bearer ' + creds.token
    }
    res = requests.post(url, data=json.dumps(payload), headers=headers)
    print(res.text)


if __name__ == '__main__':
    main()

Note:

  • In this case, you can use the scope of both https://www.googleapis.com/auth/photoslibrary.readonly and https://www.googleapis.com/auth/photoslibrary.

Reference:

Answered By: Tanaike