$ pip3 list | grep googl
google-api-python-client 1.7.9
google-auth 1.6.3
google-auth-httplib2 0.0.3
google-auth-oauthlib 0.4.0
I can successfully list files shared to me. But I get "File not found" error when I try to download an existing file by its id. How to download a file by its id?
Script to list files
from __future__ import print_function
import pickle
import os.path
import io
import sys
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
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.metadata.readonly']
TOKEN_FILE = 'tockenRead.pickle'
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_FILE):
with open(TOKEN_FILE, '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()
# Save the credentials for the next run
with open(TOKEN_FILE, 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
q="mimeType != 'application/vnd.google-apps.folder'",
pageSize=10,
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(u'{0} ({1})'.format(item['name'], item['id']))
if __name__ == '__main__':
main()
Result
$ python3 list_files.py
Files:
20140810_125633.mp4 (1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE)
Getting started (0B3K2QXOGSOFRc3RhcnRlcl9maWxl)
Script to download file with id 1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE
from __future__ import print_function
import pickle
import os.path
import io
import sys
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
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.file']
TOKEN_FILE = 'tokenWrite.pickle';
def downloadFile(driveService, fileId):
request = driveService.files().get_media(fileId=fileId)
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))
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_FILE):
with open(TOKEN_FILE, '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()
# Save the credentials for the next run
with open(TOKEN_FILE, 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
downloadFile(service, '1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE')
if __name__ == '__main__':
main()
Error
$ python3 download_files.py
Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=619229308650-91gkhdgo7v0jbt6df1phahmq868eb7gd.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file&state=4mP9kgVJQD4ETOu5JjIRQFBLcyViAG&access_type=offline&code_challenge=ybCzMgZ2SOXdrpZZYn1dq9nSJk8wMtLo7Deg_Xix9So&code_challenge_method=S256
Traceback (most recent call last):
File "download_files.py", line 52, in <module>
main()
File "download_files.py", line 49, in main
downloadFile(service, '1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE')
File "download_files.py", line 21, in downloadFile
status, done = downloader.next_chunk()
File "/usr/local/lib/python3.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/googleapiclient/http.py", line 705, in next_chunk
raise HttpError(resp, content, uri=self._uri)
googleapiclient.errors.HttpError: <HttpError 404 when requesting https://www.googleapis.com/drive/v3/files/1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE?alt=media returned "File not found: 1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE.">
How about this answer?
Reason of issue:
When I saw your scripts, I noticed that the scope of below script are different from the above script. I think that this is the reason of your issue.
At above script, https://www.googleapis.com/auth/drive.metadata.readonly is used. On the other hand, at the below script, https://www.googleapis.com/auth/drive.file is used.
The official document says about the scope of https://www.googleapis.com/auth/drive.file as follows.
View and manage Google Drive files and folders that you have opened or created with this app
This means that when your script uploads a file using the scope of https://www.googleapis.com/auth/drive.file, you can retrieve the file using the scope. But for example, when the file is manually upload to the Google Drive, the file cannot be downloaded by the scope of https://www.googleapis.com/auth/drive.file, even when the file is shared with you.
In order to download the file, how about the following workarounds?
Workaround 1:
You use the scope of https://www.googleapis.com/auth/drive or https://www.googleapis.com/auth/drive.readonly instead of https://www.googleapis.com/auth/drive.file.
Workaround 2:
If you are required to use the scope of https://www.googleapis.com/auth/drive.file, it uploads the file using the scope of https://www.googleapis.com/auth/drive.file. By this, the file can be downloaded by the scope.
Note:
When you change the scopes, please remove the file of tokenWrite.pickle and authorize the scopes again and create new tokenWrite.pickle. By this, you can use new scopes. Please be careful this.
Reference:
Scopes of Drive API, v3
If I misunderstood your question and this was not the direction you want, I apologize.
Related
This is my first time posting here so i apologize if i have not posted in the correct format!
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
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.json 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.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# 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.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
return
print('Files:')
for item in items:
print(u'{0} ({1})'.format(item['name'], item['id']))
except HttpError as error:
# TODO(developer) - Handle errors from drive API.
print(f'An error occurred: {error}')
if __name__ == '__main__':
main()
I'm trying to create a simple python script that does the following.
1.Import the necessary Libraries.
2.Connect/Authenticate to Google drive.
3.Check a folder on google drive for file names and then upload all files that are not on the drive yet from a
specific folder on computer to the checked folder on google drive.
4.repeat every hour, If no new files found then restart loop.
this is what i tried so far but i get errors when running the script, The issue is it cannot find the credentials.json file.
The credentials.json file is in the same folder as the settings.yaml and the Setup.py
I was expecting to be directed to a login page when running the script.
To be fair i know very very little about python and the most experience i have with coding would be from my old modded minecraft days using lua. on computercraft. hahah thanks for your help in advance.**
I was try to create google sheet using python in Pycharm but I try very had didn't out bugs.
here I submit my full code and show my error result.
# [START sheets_create]
from __future__ import print_function
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
def create(title):
"""
Creates the Sheet the user has access to.
Load pre-authorized user credentials from the environment.
TODO(developer) - See https://developers.google.com/identity
for guides on implementing OAuth2 for the application.\n"
"""
creds = 'conof.json'
# pylint: disable=maybe-no-member
try:
service = build('sheets', 'v4', credentials=creds)
spreadsheet = {
'properties': {
'title': title
}
}
spreadsheet = service.spreadsheets().create(body=spreadsheet,
fields='spreadsheetId') \
.execute()
print(f"Spreadsheet ID: {(spreadsheet.get('spreadsheetId'))}")
return spreadsheet.get('spreadsheetId')
except HttpError as error:
print(f"An error occurred: {error}")
return error
if __name__ == '__main__':
# Pass: title
create("mysheet1")
# [END sheets_create]
This is default code I found from google sheet development site I just added here my json file from google cloud console generated. I was hard to manage to solve library error's. I am using windows platform.
And my error's
C:\Users\pc\PycharmProjects\createShee\venv\Scripts\python.exe C:/Users/pc/PycharmProjects/createShee/mumu.py
Traceback (most recent call last):
File "C:\Users\pc\PycharmProjects\createShee\mumu.py", line 37, in <module>
create("mysheet1")
File "C:\Users\pc\PycharmProjects\createShee\mumu.py", line 19, in create
service = build('sheets', 'v4', credentials=creds)
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\discovery.py", line 298, in build
service = build_from_document(
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\discovery.py", line 604, in build_from_document
http = _auth.authorized_http(credentials)
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\_auth.py", line 124, in authorized_http
return credentials.authorize(build_http())
AttributeError: 'str' object has no attribute 'authorize'
Process finished with exit code 1
Please help me to solve this project.
The credential parameter of build() method can only accept the following objects:
credentials: oauth2client.Credentials or
google.auth.credentials.Credentials, credentials to be used for
authentication.
An easy way to create a credential object is to use the authentication in the Python Quickstart of Google Sheets API.
Just follow the Quickstart guide, change the scope to 'https://www.googleapis.com/auth/spreadsheets' and replace the try-except block with the try-except block in the Create a spreadsheet.
Your code should look like this:
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
def create(title):
creds = None
# The file token.json 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.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# 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.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('sheets', 'v4', credentials=creds)
spreadsheet = {
'properties': {
'title': title
}
}
spreadsheet = service.spreadsheets().create(body=spreadsheet,
fields='spreadsheetId') \
.execute()
print(f"Spreadsheet ID: {(spreadsheet.get('spreadsheetId'))}")
return spreadsheet.get('spreadsheetId')
except HttpError as error:
print(f"An error occurred: {error}")
return error
if __name__ == '__main__':
create("mysheet1")
Output:
Notes: Make sure to install the necessary package included in the Quickstart guide, download the credential json file, save it in the same directory as your script and rename it to credentials.json
Reference:
Module discovery
Try replacing creds = 'conof.json' with
credentials = google.oauth2.credentials.Credentials.from_authorized_user_file('conof.json)
and adding the import as necessary.
You are currently passing a string to the credentials parameter in build; however, build expects you to pass a specific type of credentials object to it. You can obtain this credential object from a JSON file using the line of code above. See this answer for more detail.
I just start learning the python scripting and I created a script using pydrive and the function is uploading all files from local folder (linux OS) to google drive but I'm planning to modify the script for my automation and add the function that can upload only the most recent file added to the local folder with no reuploading of all the files inside the folder, may I know if this is possible with python script alone?
Thank you in advance!
You dont need to use pydrive. You can use the Google api python client library directly. As far as i know pydrive does use the client library internally. There's a starter example here
Quick start python
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
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.json 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.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# 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.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
return
print('Files:')
for item in items:
print(u'{0} ({1})'.format(item['name'], item['id']))
except HttpError as error:
# TODO(developer) - Handle errors from drive API.
print(f'An error occurred: {error}')
if __name__ == '__main__':
main()
Manage uploads
file_metadata = {'name': 'photo.jpg'}
media = MediaFileUpload('files/photo.jpg', mimetype='image/jpeg')
file = drive_service.files().create(body=file_metadata,
media_body=media,
fields='id').execute()
print 'File ID: %s' % file.get('id')
For example, in my Google Drive, I have a directory called raw_pdf, is it possible to list all the files in that directory using Google Drive API?
Using the Q paramater which is part of files.list allows you to do a Files search
parents in Whether the parents collection contains the specified ID.
by sending something like
parents in 1234
where 1234 is equal to the file id of your raw_pdf directory
I recommend following the official Python quick start example which shows how to authenticate your application and how to use file.list you will just need to then add the q parameter to the request.
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
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
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)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, 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(u'{0} ({1})'.format(item['name'], item['id']))
if __name__ == '__main__':
main()
I am trying to upload a file to Google Drive using its Python API since I need to make a script to upload automatic backup copies from my server to Google Drive if user interaction. I have the following code which I have extracted from the Google Drive documentation.
Code of my 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
from apiclient.http import MediaFileUpload
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
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()
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, 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(u'{0} ({1})'.format(item['name'], item['id']))
file_metadata = {
'name' : 'report.csv',
'mimeType' : 'application/vnd.google-apps.spreadsheet'
}
media = MediaFileUpload('files/report.csv',
mimetype='text/csv',
resumable=True)
file = drive_service.files().create(body=file_metadata,
media_body=media,
fields='id').execute()
print ("File ID: %s" % file.get("id"))
main()
The errors that it shows me are these:
Traceback (most recent call last):
File "gdriveprueba.py", line 55, in <module>
resumable=True)
File "/home/servicioweb/.local/lib/python2.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/home/servicioweb/.local/lib/python2.7/site-packages/googleapiclient/http.py", line 554, in __init__
fd = open(self._filename, 'rb')
IOError: [Errno 2] No such file or directory: 'files/report.csv'
the files directory create it manually in Google Drive but it keeps telling me that it can not find it, what could be happening that I can not see? I have 2 days in this and I have not been able to upload the files from the script.
You are confusing the parameters on line 50 and line 53. The parameter name which goes in the file_metadata structure is referring to the name of the file on the google drive. The first parameter to the MediaFileUpload constructor refers to the path on the local drive. For your code to work this file needs to exist. Also you are referring to an undefined variable drive_service on line 56. You can either redefine the variable service, which is defined in the main function, as a global variable, or move the code which requests the api upload (starting on line 49) into the function main. Also main needs to be called first before your upload code to actually create the service object.
If you just want to upload this to the root of your drive, you can just create the file files/report.csv, relative to this file, and you will have the file report.csv created on the root of your drive.
To create the file files/report.csv, you need to find the fileId of the directory files on your google drive, and send that as a parameter to the create api call.
To find the fileId run this code:
dirp = "files" # Name of directory to find.
parent_id = "" # The id we are looking for.
query = ("name='%s'" % (dirp))
resp = service.files().list(
q=query,
fields="files(id, name)",
pageToken=None).execute()
files = resp.get('files', [])
if len(files) > 0:
parent_id = files[0].get('id')
Now use the variable parent_id in the api request to create the file.
media = MediaFileUpload('report.csv',
mimetype='text/csv',
resumable=True)
meta_data= { 'name': 'report.csv',
'mimeType' : 'application/vnd.google-apps.spreadsheet',
'parents': [parent_id] }
f = service.files().create(
body=meta_data,
media_body=media,
fields='id').execute()
if not f is None: print("[*] uploaded %s" % (f.get('id')))
Here is more info on the parameters for the create function.
The working code would look like this:
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
from apiclient.http import MediaFileUpload
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
service = None
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.
"""
global service
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()
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, 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(u'{0} ({1})'.format(item['name'], item['id']))
main()
# Retrieve the parent ID of the files/ directory
dirp = "files" # Name of directory to find.
parent_id = "" # The id we are looking for.
query = ("name='%s'" % (dirp))
resp = service.files().list(
q=query,
fields="files(id, name)",
pageToken=None).execute()
files = resp.get('files', [])
# Create a file object for file 'report.csv' on your local drive.
media = MediaFileUpload('report.csv',
mimetype='text/csv',
resumable=True)
# Upload the file.
if len(files) > 0:
parent_id = files[0].get('id')
meta_data= { 'name': 'report.csv',
'parents': [parent_id],
'mimeType' : 'application/vnd.google-apps.spreadsheet' }
f = service.files().create(
body=meta_data,
media_body=media,
fields='id').execute()
if not f is None: print("[*] uploaded %s" % (f.get('id')))
else: print("The folder files/ does not exist on your drive.")