In their documentation, google show the example of how to read a sheet using their API. it requires you to manually find the google sheet ID first from the url. However, I would like to just give a google drive directory, and find the sheet id of all the google sheets in that drive. How can I do that?
Code tried:
from google.oauth2 import service_account
from googleapiclient.discovery import build
sheetMymeType = "application/vnd.google-apps.spreadsheet"
parent = PARENTFOLDER_ID
SERVICE_ACCOUNT_FILE = 'keys.json'
SCOPES = ['https://www.googleapis.com/auth/drive.readonly']
credentials = None
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
drive = build('drive', 'v3', credentials=credentials)
q = "mimeType = '{}' and parents = '{}'".format(sheetMymeType, parent)
list = drive.files().list(q=q, fields='files(id)').execute()
print(list)
In your case you need to use the Google Drive API, in specific the Files.list method.
As you can see in the documentation for Search files and folders you can supply a q parameter in order to search for a determined type of file. As your goal is give a google drive directory, and find the sheet id of all the google sheets in that drive you need to use two query terms:
mimeType in your case application/vnd.google-apps.spreadsheet (you can review the full list of Google Workspace and Drive MIME Types here)
parent the ID of the folder that you want to use.
And, as you need to retrieve those who accomplish the two requeriments you need to use the query operator and
sample.py
def get_all_sheets_in_folder():
drive = build('drive', 'v3', credentials=creds)
sheetMymeType = "application/vnd.google-apps.spreadsheet"
parent = 'SOME_FOLDER_ID'
q = "mimeType = '{}' and parents in '{}'".format(sheetMymeType, parent)
list = drive.files().list(q=q, fields='files(id)').execute()
print(list)
I recommend you review the quickstart.py in order to know how to set up your project.
Related
I am able to create a sheet with the code below in the root of ‘My Drive’ but how do I create the sheet under a folder in “My Drive” or “Shared drives”?
from googleapiclient.discovery import build
service = build(‘sheets’, ‘v4’, credentials=creds)
sheet = service.spreadsheets()
body = {}
results = sheet.create(body=body).execute()
pprint(results)
You want to create new Spreadsheet in the specific folder.
You want to achieve this using google-api-python-client with python.
If my understanding is correct, how about this answer?
Issue:
Unfortunately, in the current stage, new Spreadsheet cannot be directly created to the specific folder of Google Drive using Sheets API. In this case, Drive API is required to be used.
Sample script:
Before you run the script, please set the folder ID.
Pattern 1:
In this pattern, the new Spreadsheet is directly created to the specific folder in your Google Drive. In order to create Spreadsheet, the mimeType of application/vnd.google-apps.spreadsheet is used.
Script:
drive = build('drive', 'v3', credentials=creds)
file_metadata = {
'name': 'sampleName',
'parents': ['### folderId ###'],
'mimeType': 'application/vnd.google-apps.spreadsheet',
}
res = drive.files().create(body=file_metadata).execute()
print(res)
Pattern 2:
In this pattern, after the new Spreadsheet is created by Sheets API, the Spreadsheet is moved to the specific folder in your Google Drive.
Script:
# Create Spreadsheet to the root folder.
service = build('sheets', 'v4', credentials=creds)
sheet = service.spreadsheets()
body = {}
results = sheet.create(body=body).execute()
pprint(results)
# Move the created Spreadsheet to the specific folder.
drive = build('drive', 'v3', credentials=creds)
folderId = '### folderId ###'
res = drive.files().update(fileId=results['spreadsheetId'], addParents=folderId, removeParents='root').execute()
print(res)
Note:
For both samples, please add a scope of https://www.googleapis.com/auth/drive. And when the scopes are added, please remove the created credential file including the refresh token and authorize again. By this, the additional scopes are reflected to the refresh token.
If you want to use the shared Drive, please modify as follows.
For pattern 1
file_metadata = {'name': 'sampleName','parents': ['### folderId ###'],'mimeType': 'application/vnd.google-apps.spreadsheet','driveId': "###"}
res = drive.files().create(body=file_metadata, supportsAllDrives=True).execute()
For pattern 2
res = drive.files().update(fileId=results['spreadsheetId'], body={'driveId': "###"}, addParents=folderId, removeParents='root', supportsAllDrives=True).execute()
References:
Files: create
Files: update
If I misunderstood your question and this was not the direction you want, I apologize.
in this code :
file_id = '0BwwA4oUTeiV1UVNwOHItT0xfa2M'
request = drive_service.files().get_media(fileId=file_id)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print "Download %d%%." % int(status.progress() * 100)
I don't know how to get file_id , I was getting file_id while uploading but now I am not able to figure out how to get file_id of the file which is present on Google Drive.
Ex. if my uploaded file has name A001002.pdf , how can i get file id for this file.
there is some reference online which i am not able to understand.
link: files.list
any help?
The file.list method contains a q paramater which is used for searching
GET https://www.googleapis.com/drive/v3/files?q=name+%3D+'hello'&key={YOUR_API_KEY}
Python Guess
"""
Shows basic usage of the Drive v3 API.
Creates a Drive v3 API service and prints the names and ids of the last 10 files
the user has access to.
"""
from __future__ import print_function
from apiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
# Setup the Drive v3 API
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.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('drive', 'v3', http=creds.authorize(Http()))
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="*").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print('{0} ({1})'.format(item['name'], item['id']))
Note this example does not show how to add the additional parameter i am still Googling that but i am not a python dev you may know more about how to do that than me.
Depending on your implementation, there is one more alternative. In case you do not need to programmatically get the fileID you can just open the file in google docs from the browser and the ID is shown in the URL.
I'm trying to get data that lives within a Google Sheet into our Redshift database. I was able to follow the directions from this link: https://www.twilio.com/blog/2017/02/an-easy-way-to-read-and-write-to-a-google-spreadsheet-in-python.html
Is it possible to have it pull data from the most recently added google sheets within a folder (instead of just specifying a single sheet) and write to the Redshift table?
Here is what was used to read the google sheets data into Python:
import gspread
from oauth2client.service_account import ServiceAccountCredentials
# use creds to create a client to interact with the Google Drive API
scope = ['https://spreadsheets.google.com/feeds']
creds = ServiceAccountCredentials.from_json_keyfile_name('client_secret.json', scope)
client = gspread.authorize(creds)
# Find a workbook by name and open the first sheet
# Make sure you use the right name here.
sheet = client.open("Copy of Legislators 2017").sheet1
# Extract and print all of the values
list_of_hashes = sheet.get_all_records()
print(list_of_hashes)
You can use the Drive API to query for files added within a given timeframe that are of a specific type. All the search parameters and syntax for such a query are listed here.
# Build the Drive service
...
# Query for recent files, with stipulation that their mimetype contains "spreadsheet"
query = "mimeType contains 'spreadsheet' and modifiedTime > '"
query += someDateAsUTC_inRFC_3339_String + "'"
# Execute the query
request = drive.files.list(q=query, .... )
resp = request.execute()
nextPage = resp['nextPageToken']
if resp['files']:
# Call method to consume files
while nextPage:
request = drive.files.list_next(request, resp)
if request:
resp = request.execute()
nextPage = resp['nextPageToken']
if resp['files']:
# Call method to consume files
else
break
# Done
I've just started trying to use the Google Drive API. Using the quickstart guide I set up the authentication, I can print a list of my files and I can even make copies. All that works great, however I'm having trouble trying to access data from a file on Drive. In particular, I'm trying to get a WebViewLink, however when I call .get I receive only a small dictionary that has barely any of the file's metadata. The documentation makes it look like all the data should just be there by default but it's not appearing. I couldn't find any way to flag for requesting any additional information.
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('drive', 'v3', http=http)
results = service.files().list(fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print(item['name'], item['id'])
if "Target File" in item['name']:
d = service.files().get(fileId=item['id']).execute()
print(repr(d))
This is the output of the above code: (the formatting is my doing)
{u'mimeType': u'application/vnd.google-apps.document',
u'kind': u'drive#file',
u'id': u'1VO9cC8mGM67onVYx3_2f-SYzLJPR4_LteQzILdWJgDE',
u'name': u'Fix TVP Licence Issues'}
For anyone confused about the code there is some missing that's just the basic get_credentials function from the API's quickstart page and some constants and imports. For completeness, here's all that stuff, unmodified in my code:
from __future__ import print_function
import httplib2
import os
from apiclient import discovery
import oauth2client
from oauth2client import client
from oauth2client import tools
SCOPES = 'https://www.googleapis.com/auth/drive'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Drive API Python Quickstart'
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
def get_credentials():
"""Gets valid user credentials from storage.
If nothing has been stored, or if the stored credentials are invalid,
the OAuth2 flow is completed to obtain the new credentials.
Returns:
Credentials, the obtained credential.
"""
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir,
'drive-python-quickstart.json')
store = oauth2client.file.Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatibility with Python 2.6
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
So what's missing, how can I get the API to return all that extra meta data that's just not appearing right now?
You are very close. With the newer version of the Drive API v3, to retrieve other metadata properties, you will have to add the fields parameter to specify additional properties to include in a partial response.
In your case, since you are looking to retrieve the WebViewLinkproperty your request should look something similar to this:
results = service.files().list(
pageSize=10,fields="nextPageToken, files(id, name, webViewLink)").execute()
To display your items from the response:
for item in items:
print('{0} {1} {2}'.format(item['name'], item['id'], item['webViewLink']))
I also suggest try it out with the API Explorer so you can view what additional metadata properties you would like to display on your response.
Good Luck and Hope this helps ! :)
You explicitly request only the id and name fields in your files.list call. Add webViewLink to the list to results = service.files().list(fields="nextPageToken, files(id, name, webViewLink)").execute(). To retrieval all metadata files/* should be used. For more information about this performance optimizations see Working with partial resources in the Google Drive docs.
I have written a custom function to help with getting a sharable web link given a file/folder id. More information can be gotten here
def get_webViewLink_by_id(spreadsheet_id):
sharable_link_response = drive_service.files().get( fileId=spreadsheet_id, fields='webViewLink').execute()
return(sharable_link_response['webViewLink'])
print(get_webViewLink_by_id(spreadsheet_id = '10Ik3qXK4wseva20lNGUKUTBzKoywaugi6XOmRUoP-4A'))
Does anyone know where I can find complete sample code for uploading a local file and getting contents with MediaFileUpload?
I really need to see both the HTML form used to post and the code to accept it. I'm pulling my hair out and so far only getting partial answers.
I found this question while trying to figure out where the heck "MediaFileUpload" came from in the Google API examples, and I eventually figured it out. Here is a more complete code example that I used to test things with Python 2.7.
You need a JSON credentials file for this code to work. This is the credentials file you get from your Google app / project / thing.
You also need a file to upload, I'm using "test.html" here in the example.
from oauth2client.service_account import ServiceAccountCredentials
from apiclient.discovery import build
from apiclient.http import MediaFileUpload
#Set up a credentials object I think
creds = ServiceAccountCredentials.from_json_keyfile_name('credentials_from_google_app.json', ['https://www.googleapis.com/auth/drive'])
#Now build our api object, thing
drive_api = build('drive', 'v3', credentials=creds)
file_name = "test"
print "Uploading file " + file_name + "..."
#We have to make a request hash to tell the google API what we're giving it
body = {'name': file_name, 'mimeType': 'application/vnd.google-apps.document'}
#Now create the media file upload object and tell it what file to upload,
#in this case 'test.html'
media = MediaFileUpload('test.html', mimetype = 'text/html')
#Now we're doing the actual post, creating a new file of the uploaded type
fiahl = drive_api.files().create(body=body, media_body=media).execute()
#Because verbosity is nice
print "Created file '%s' id '%s'." % (fiahl.get('name'), fiahl.get('id'))
A list of valid Mime Types to use in the "body" hash is available at
https://developers.google.com/drive/v3/web/mime-types
A list of valid mimetype strings for the MediaFileUpload (they'll attempt to convert your file to whatever you put here):
https://developers.google.com/drive/v3/web/integrate-open#open_files_using_the_open_with_contextual_menu
Python 2.7, resumable upload.
https://github.com/googleapis/google-api-python-client/blob/master/docs/media.md
from __future__ import print_function
import pickle
import os.path
from googleapiclient.http import MediaFileUpload
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive']
def main():
"""Shows basic usage of the Drive v3 API.
Prints the names and ids of the first 10 files the user has access to.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
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(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
media = MediaFileUpload(
'big.jpeg',
mimetype='image/jpeg',
resumable=True
)
request = service.files().create(
media_body=media,
body={'name': 'Big', 'parents': ['<your folder Id>']}
)
response = None
while response is None:
status, response = request.next_chunk()
if status:
print("Uploaded %d%%." % int(status.progress() * 100))
print("Upload Complete!")
if __name__ == '__main__':
main()
You won't need to post JSON yourself, the client library handles that for you.
We provide full code samples already which can be found here: https://github.com/gsuitedevs/python-samples
Also you could check the file.insert reference documentation which contains a Python sample: https://developers.google.com/drive/v2/reference/files/insert
If this does not answer what you want perhaps you could explain in more details what you want to achieve and your architecture currently in place.
I want to provide additional information on uploading to a specific drive folder. I am providing the example from my AWS Lambda with Python 3.7
Note:
You need the folder ID for your desired location. You can find this by going to your drive folder and looking for the ID in the URL in the Browser.
For example in this URL, https://drive.google.com/drive/u/0/folders/1G91IKgQqI9YgNj8Odc8SIOPHrWOjdvOO, 1G91IKgQqI9YgNj8Odc8SIOPHrWOjdvOO would be your ID.
You need to provide your service account email access to the folder to be accessed. The service account email is found in the IAM section of your Google Cloud account. Add access to your folder by going to it in Drive, clicking the "i" icon on the top right, clicking details, then manage access.
You also need the JSON file associated with the service account. Find/create this in the Service Accounts section in Google Cloud IAM on the KEYS tab. The file contains the private key for your project. Store it where your code can access.
I'm not sure which dependencies you need to install but I think
pydrive installed them all for me: pip3 install pydrive
from apiclient.discovery import build
from google.oauth2 import service_account
from googleapiclient.http import MediaFileUpload
# This provides what authority the service account has as well as the location of the JSON file containing the private key.
scopes = ['https://www.googleapis.com/auth/drive']
service_account_file = 'path/to/service_account.json'
# Create the credentials object for the service account
credentials = service_account.Credentials.from_service_account_file(service_account_file, scopes=scopes)
drive = build('drive', 'v3', credentials=credentials)
# Create the metadata for the file and upload it to the drive folder. Supply the corresponding MIME type for your file. The parents parameter is very important, this is where you supply the ID you found for your drive folder.
body = {'name': 'testfile.txt', 'mimeType': 'text/plain', 'parents': ["theStringForTheDriveFolder"]}
media = MediaFileUpload('path/to/testfile.txt', mimeType='text/plain')
drive.files().create(body=body, media_body=media).execute()
Here's the documentation I followed:
How to use service accounts to call google APIs: https://developers.google.com/identity/protocols/oauth2/service-account#python
Documentation for the Drive API V3 to upload files:
https://developers.google.com/drive/api/v3/reference/files/create
Documentation for the Google-Python API client:
https://github.com/googleapis/google-api-python-client/blob/main/docs/oauth.md
How to perform various upload types with the Drive API:
https://developers.google.com/drive/api/guides/manage-uploads#simple
How to create and use Service Accounts, including generating the JSON
file/private keys:
https://developers.google.com/identity/protocols/oauth2/service-account