1

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']))
Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
KFunk
  • 2,956
  • 22
  • 33

1 Answers1

3
  • 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:

Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • I'm not certain, but I *think* that `InstalledAppFlow` is the same as a "Service Account" that Google Photos API mentions that it [doesn't support](https://developers.google.com/photos/library/guides/authentication-authorization), so when I run this with my OAuth 2.0 client ID `client_secret.json`, I get the error `ValueError: Client secrets must be for a web or installed app.`. Also, the `googleapiclient` library doesn't fully work with the Google Photos API. – KFunk Nov 20 '19 at 07:46
  • @KFunk Thank you for replying. Unfortunately, I cannot understand about your replying. This is due to my poor English skill. I deeply apologize for this. I thought that you want to use OAuth2 from your question and script. Is my understanding correct? Also I cannot understand about the error, because in my environment, I can confirm that the script works . Can you provide the detail flow for replicating your issue? By this, I would like to confirm it. If you can cooperate to resolve your issue, I'm glad. – Tanaike Nov 20 '19 at 08:23
  • My mistake. I was mixing up my credentials files. Google refers to these credential files as credentials.json/client_secret.json whether or not it's for [oauth or a service account key](https://console.developers.google.com/apis/credentials), and it's confusing. The issue that still remains for me is that [google-api-python-client](https://github.com/googleapis/google-api-python-client) doesn't fully work with Google Photos API. I guess I need to make these requests, and authenticate using the `requests` library. – KFunk Nov 20 '19 at 08:49
  • @KFunk Thank you for replying. Unfortunately, I cannot understand about `The issue that still remains for me is that google-api-python-client doesn't fully work with Google Photos API.`. Can I ask you about your current situation? When you use my sample script, does the error occur? Because when I use it, I can confirm that the script works. So I would like to confirm your current issue. – Tanaike Nov 20 '19 at 08:56
  • https://github.com/googleapis/google-api-python-client/issues/733 – KFunk Nov 20 '19 at 23:03
  • @KFunk Thank you for replying. Unfortunately, I cannot understand about your replying. In my environment, I could confirm that my script worked fine. I would like to confirm your current issue. When you use my sample script, does the error occur? – Tanaike Nov 20 '19 at 23:10
  • Your script works. The problem is that google-api-python-client will not work for all Google Photos API features. If you see the link I posted, you will see an example where that library fails, and there is no plans for google to fix it. I need to replace that library with something else. What I need to solve, specifically, is fetching the images within an album, as in github.com/googleapis/google-api-python-client/issues/733 – KFunk Nov 21 '19 at 00:00
  • @KFunk Thank you for replying. From your replying, I could understand that my script worked in your environment. And from your replying, it seems that you want to use [the method of mediaItems.search](https://developers.google.com/photos/library/reference/rest/v1/mediaItems/search). Although I'm not sure about the situation when [the post](https://github.com/googleapis/google-api-python-client/issues/733) was posted, in the current stage, `service.mediaItems().search()` works. But the request body is different from the post. I updated my answer. Could you please confirm it? – Tanaike Nov 21 '19 at 00:19
  • @KFunk Did my answers for your 2 questions show you the result what you want? Would you please tell me about it? That is also useful for me to study. If this works, other people who have the same issue with you can also base your question as a question which can be solved. If you have issues for my answer yet, I apologize. At that time, can I ask you about your current situation? I would like to study to solve your issues. – Tanaike Nov 25 '19 at 01:18
  • this does solve my immediate problem, but this does make my current code work... but I was looking for a solution that doesn't use unsupported libraries, as mentioned in https://github.com/googleapis/google-api-python-client/issues/733 – KFunk Dec 02 '19 at 22:45
  • @KFunk Thank you for replying. I couldn't understand that you wanted to use Photos API without using google-api-python-client from your question. This is due to my poor English skill. I deeply apologize for this. If my understanding of your direction is correct, can I ask you about the method of Photos API you want to use? And in this case, how do you retrieve the access token? When I propose a sample script, can I suppose that you have already had the access token? – Tanaike Dec 02 '19 at 22:54
  • It seems like the python `requests` library is the solution suggested. Google auth libraries appear to still be supported, so those two together will work. I have the `credentials.json` as mentioned in your code above. – KFunk Dec 05 '19 at 03:32
  • @KFunk Thank you for replying. I have to apologize for my poor English skill. 1. Can you update your question by including the script for authorizing you want? 2. In my answer, I have already answered that `albums().list` and `mediaItems().search()` works using google-api-python-client. This is due to your requests. In this situation, can I ask you about the method of Photos API that you want to use and google-api-python-client cannot be used? Because I'm not sure the method of Photos API you want to use with python `requests`. If you can cooperate to resolve your issue, I'm glad. – Tanaike Dec 05 '19 at 04:41
  • The original goal is to not use any deprecated libraries. `google-api-python-client` is deprecated. I don't want to use it. Authorization: still `google_auth_oauthlib.flow` and `google.auth.transport.requests.` (if possible). Request library to the Google Photos API: `requests`. Data to get: list of mediaItems in an album *without* using the deprecated `google-api-python-client` library. – KFunk Dec 05 '19 at 08:27
  • @KFunk Thank you for replying. From your replying, I added one more sample script. Could you please confirm it? If that was not the direction you want, I apologize. – Tanaike Dec 05 '19 at 09:12
  • @KFunk Did my answer show you the result what you want? Would you please tell me about it? That is also useful for me to study. If this works, other people who have the same issue with you can also base your question as a question which can be solved. If you have issues for my answer yet, I apologize. At that time, can I ask you about your current situation? I would like to study to solve your issues. – Tanaike Dec 10 '19 at 02:44
  • @KFunk Is there anything that I can do for your question? If my answer was not useful for your situation. I have to apologize and modify it. If you can cooperate to resolve your issue, I'm glad. I would like to think of about the solution. – Tanaike Dec 15 '19 at 22:30
  • @KFunk Thank you for replying. I'm glad your issue was resolved. I could study from your question. Thank you, too. – Tanaike Dec 17 '19 at 23:11