12

I try to access shared Google Drive files through Python.

I have created an OAuth 2.0 ClientID as well as the OAuth consent.

I have copy-pasted this code: https://github.com/googleworkspace/python-samples/blob/master/drive/quickstart/quickstart.py

The authorization is successful, however, the Python code returns a blank list indicating there are no files in Google Drive, although there are many.

Should there be a difference because I am trying to access a shared folder, if yes, could it cause the error, and how this can be solved?

If not, is this the right approach? I read about API keys and Service Accounts as well, would it make sense to use either of them? Later this service I create will be used by other users on Databricks (running on AWS), and I do not know which solution would be the best one.

Thank you for your help!

Szabolcs Magyar
  • 369
  • 1
  • 2
  • 11

5 Answers5

7

Have you tried to use the PyDrive library?

https://pypi.org/project/PyDrive/

You can use the PyDrive wrapper library to get high level functions that you can use to access the Google Drive API.

PyDrive also uses OAuth2.0 and you can get setup with just a couple of lines:

from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

gauth = GoogleAuth()
gauth.LocalWebserverAuth()

drive = GoogleDrive(gauth)

You can get a file like so:

# or download Google Docs files in an export format provided.
# downloading a docs document as an html file:
docsfile.GetContentFile('test.html', mimetype='text/html')

The Wrapper also allows you to create and upload files easily:

file1 = drive.CreateFile({'title': 'Hello.txt'})
file1.SetContentString('Hello')
file1.Upload() # Files.insert()

You can get more documentation and examples using the link I sent previously. Cheers!

XtremeDevX
  • 1,482
  • 2
  • 13
  • 38
7

I ended up using this code which helped me achieve it:

from __future__ import print_function
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials

scope = ['https://www.googleapis.com/auth/drive.readonly']

credentials = ServiceAccountCredentials.from_json_keyfile_name('service_account_key.json', scope)

# https://developers.google.com/drive/api/v3/quickstart/python
service = build('drive', 'v3', credentials=credentials)

# Call the Drive v3 API
results = service.files().list(
    fields="*",corpora = 'drive',supportsAllDrives = True, driveId = "YOUR_DRIVE_ID", includeItemsFromAllDrives = True).execute()
items = results.get('files', [])

if not items:
    print('No files found.')
else:
    print('Files:')
    for item in items:
        print(u'{0} ({1})'.format(item['name'], item['id']))

The service account is important because then users do not need to authenticate themselves on-by-one.

Key takeaways of this solution:

  • You need to share the service account address with the Google Drive
  • driveId is needed if you want to access a shared drive
  • For a shared drive, you need corpora, supportsAllDrives and includeItemsForAllDrives to be set for the same as in the code
  • The scope should be aligned with the permission your service account has in the shared folder
Szabolcs Magyar
  • 369
  • 1
  • 2
  • 11
3

I used pydrive2 following code worked for me

from pydrive2.auth import GoogleAuth
from oauth2client.service_account import 
ServiceAccountCredentials
from pydrive2.drive import GoogleDrive

gauth = GoogleAuth()

gauth.credentials = ServiceAccountCredentials.from_json_keyfile_name('credentials.json', SCOPES)
drive = GoogleDrive(gauth)
query = "'{}' in parents and trashed=false"
query=query.format(folder_id)
file_list = drive.ListFile({'q': query}).GetList()

Make sure credentials file is in the same folder and the drive which you are trying to access shares the folder with the email on which your service or developer account is made. For more detail see my blog https://medium.com/@zakriya57/integrating-google-drive-in-your-application-1c3012fef396

2

Using google api:

from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


scope = ['https://www.googleapis.com/auth/drive.readonly']
credentials = ServiceAccountCredentials.from_json_keyfile_name("service_account_key.json", scope)

try:
    service = build("drive", "v3", credentials=creds)
    files = []
    page_token = None
    while True:
        response = service.files().list(
            spaces="drive",
            fields="nextPageToken, files(id, name)",
            pageToken=page_token).execute()
        for file in response.get("files", []):
            print(f"Found file: {file.get('name')}, {file.get('id')}")
        files.extend(response.get("files", []))
        page_token = response.get("nextPageToken", None)
        if page_token is None:
            break
except HttpError as error:
    print(f"An error occurred: {error}")
    files = None

This will return all the files stored on a google disc that were created by the user or shared directly with the user. If you need a larger scope, use parameter corpora. Read here about it.

Additionally, it is possible to specify a query string using parameter q:

response = service.files().list(
    q="mimeType='image/jpeg' and name contains '01-01-2023' and 'FOLDER_ID' in parents",
    spaces="drive",
    fields="nextPageToken, files(id, name)",
    pageToken=page_token).execute()

This will return all the pictures (jpeg) from a specific folder with '01-01-2023' in the file's name.

Cookie
  • 113
  • 1
  • 5
1

I use google.colab:

from google.colab import drive
drive.mount('/content/drive')
!ls

The rest will be similar to other solution, you need to allow access to the folder you would like to access.

corngk
  • 31
  • 4