Python:从 google 驱动器 api 下载文件时出现问题,超出了未经身份验证使用的每日限制
Python: Issues downloading file from google drive api, getting daily limit for unauthenticated use exceeded
问题陈述:
当我尝试从 google 驱动器 api 为我的 python 应用程序下载文件时,我遇到了一个问题。我今天才开始使用它,所以我可能在做一些愚蠢的事情,所以请耐心等待 :)。
我遇到的问题是,在使用驱动器-api 验证我的应用程序后,我可以从 google 驱动器读取文件和元数据,但我无法下载它们。下面贴出相关代码供参考。
遵循的步骤:
我首先按照说明启用了 OAuth2,并获取了凭据。json/client_secrets。json。我确保范围在权限方面是正确的,然后生成了我的 pickle 文件。从那里,我使用文档和快速入门指南中的代码来编写我的代码。从那里,我无法取得任何进展。我认为我可能需要对我的应用程序进行安全评估,但我不打算发布它,所以我认为这种级别的权限对开发人员来说没问题。
我看到许多其他关于此的堆栈溢出帖子,但我没有得到任何帮助(我以为我遵循了所有相同的步骤来验证并为我的应用程序启用 drive-api 权限)。
我还无法下载单个文件,所以我认为我没有达到每日限制。我认为我没有正确进行请求身份验证,但我找不到任何相关文档。如果有任何帮助,我将不胜感激。
参考代码:
我所有的代码都是直接从文档中获取的。以下是相关的 links:
- 授权和列表文件:https://developers.google.com/drive/api/v3/quickstart/python
- 下载文件:https://developers.google.com/drive/api/v3/manage-downloads
- delete_file: https://developers.google.com/drive/api/v3/reference/files/delete#auth
初始化代码如下:
# packages
from __future__ import print_function
import pickle
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from apiclient import errors
from googleapiclient.http import MediaIoBaseDownload
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive'] # set permisions to read/write/delete
creds = None
if os.path.exists('token.pickle'):
with open('token.pickle', '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(
'client_secrets.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
drive = build('drive', 'v3', credentials=creds)
这是我的驱动器下载功能:
def download_from_drive_to_local(drive, fname):
# search for image in drive
file_search = drive.files().list(
q=f"name = '{fname}'",
spaces='drive',
fields="nextPageToken, files(id, name)").execute()
items = file_search.get('files', [])
print('Files retrieved: ', items)
# download retrieved image from drive
item_ids = [i['id'] for i in items]
if len(item_ids) > 1: print("Warning: multiple files exist with the same name. Using first file found.")
for i in items:
request = drive.files().get_media(fileId=i)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
break
# delete retrieved image from drive
for i in items:
try:
drive.files().delete(fileId=i).execute()
except errors.HttpError as error:
print(f'An error occured deleting file id <{i}>: {error}.')
# write bytearray to file
with open(os.path.join(self.download_dir, f'{fname}.tif'), 'wb') as file: file.write(fh)
还有我的错误结果:
点击 link 给我这个:
修改点:
当我看到你的脚本时,我认为 for i in items:
的 items
来自 items = file_search.get('files', [])
。在这种情况下,i
就像 {'name': '###', 'id': '###'}
。当它被用作 request = drive.files().get_media(fileId=i)
的 i
时,文件被用作 {'name': '###', 'id': '###'}
。我认为这就是您遇到问题的原因。
并且,当您使用fh = io.BytesIO()
将下载的数据保存为文件时,保存脚本如下
with io.open(filename, 'wb') as f:
fh.seek(0)
f.write(fh.read())
当item_ids
的长度为0
时,出现错误
当以上几点反映到你的脚本中,就变成了下面这样。
修改后的脚本:
从:
# download retrieved image from drive
item_ids = [i['id'] for i in items]
if len(item_ids) > 1: print("Warning: multiple files exist with the same name. Using first file found.")
for i in items:
request = drive.files().get_media(fileId=i)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
break
# delete retrieved image from drive
for i in items:
try:
drive.files().delete(fileId=i).execute()
except errors.HttpError as error:
print(f'An error occured deleting file id <{i}>: {error}.')
# write bytearray to file
with open(os.path.join(self.download_dir, f'{fname}.tif'), 'wb') as file: file.write(fh)
到:
# download retrieved image from drive
item_ids = [i['id'] for i in items]
if len(item_ids) > 1:
print("Warning: multiple files exist with the same name. Using first file found.")
for i in item_ids:
request = drive.files().get_media(fileId=i)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
break
# delete retrieved image from drive
for i in item_ids:
try:
drive.files().delete(fileId=i).execute()
except errors.HttpError as error:
print(f'An error occured deleting file id <{i}>: {error}.')
# write bytearray to file
if item_ids != []:
with io.open(os.path.join(self.download_dir, f'{fname}.tif'), 'wb') as f:
fh.seek(0)
f.write(fh.read())
问题陈述:
当我尝试从 google 驱动器 api 为我的 python 应用程序下载文件时,我遇到了一个问题。我今天才开始使用它,所以我可能在做一些愚蠢的事情,所以请耐心等待 :)。
我遇到的问题是,在使用驱动器-api 验证我的应用程序后,我可以从 google 驱动器读取文件和元数据,但我无法下载它们。下面贴出相关代码供参考。
遵循的步骤:
我首先按照说明启用了 OAuth2,并获取了凭据。json/client_secrets。json。我确保范围在权限方面是正确的,然后生成了我的 pickle 文件。从那里,我使用文档和快速入门指南中的代码来编写我的代码。从那里,我无法取得任何进展。我认为我可能需要对我的应用程序进行安全评估,但我不打算发布它,所以我认为这种级别的权限对开发人员来说没问题。 我看到许多其他关于此的堆栈溢出帖子,但我没有得到任何帮助(我以为我遵循了所有相同的步骤来验证并为我的应用程序启用 drive-api 权限)。
我还无法下载单个文件,所以我认为我没有达到每日限制。我认为我没有正确进行请求身份验证,但我找不到任何相关文档。如果有任何帮助,我将不胜感激。
参考代码:
我所有的代码都是直接从文档中获取的。以下是相关的 links:
- 授权和列表文件:https://developers.google.com/drive/api/v3/quickstart/python
- 下载文件:https://developers.google.com/drive/api/v3/manage-downloads
- delete_file: https://developers.google.com/drive/api/v3/reference/files/delete#auth
初始化代码如下:
# packages
from __future__ import print_function
import pickle
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from apiclient import errors
from googleapiclient.http import MediaIoBaseDownload
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive'] # set permisions to read/write/delete
creds = None
if os.path.exists('token.pickle'):
with open('token.pickle', '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(
'client_secrets.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
drive = build('drive', 'v3', credentials=creds)
这是我的驱动器下载功能:
def download_from_drive_to_local(drive, fname):
# search for image in drive
file_search = drive.files().list(
q=f"name = '{fname}'",
spaces='drive',
fields="nextPageToken, files(id, name)").execute()
items = file_search.get('files', [])
print('Files retrieved: ', items)
# download retrieved image from drive
item_ids = [i['id'] for i in items]
if len(item_ids) > 1: print("Warning: multiple files exist with the same name. Using first file found.")
for i in items:
request = drive.files().get_media(fileId=i)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
break
# delete retrieved image from drive
for i in items:
try:
drive.files().delete(fileId=i).execute()
except errors.HttpError as error:
print(f'An error occured deleting file id <{i}>: {error}.')
# write bytearray to file
with open(os.path.join(self.download_dir, f'{fname}.tif'), 'wb') as file: file.write(fh)
还有我的错误结果:
点击 link 给我这个:
修改点:
当我看到你的脚本时,我认为
for i in items:
的items
来自items = file_search.get('files', [])
。在这种情况下,i
就像{'name': '###', 'id': '###'}
。当它被用作request = drive.files().get_media(fileId=i)
的i
时,文件被用作{'name': '###', 'id': '###'}
。我认为这就是您遇到问题的原因。并且,当您使用
fh = io.BytesIO()
将下载的数据保存为文件时,保存脚本如下with io.open(filename, 'wb') as f: fh.seek(0) f.write(fh.read())
当
item_ids
的长度为0
时,出现错误
当以上几点反映到你的脚本中,就变成了下面这样。
修改后的脚本:
从:# download retrieved image from drive
item_ids = [i['id'] for i in items]
if len(item_ids) > 1: print("Warning: multiple files exist with the same name. Using first file found.")
for i in items:
request = drive.files().get_media(fileId=i)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
break
# delete retrieved image from drive
for i in items:
try:
drive.files().delete(fileId=i).execute()
except errors.HttpError as error:
print(f'An error occured deleting file id <{i}>: {error}.')
# write bytearray to file
with open(os.path.join(self.download_dir, f'{fname}.tif'), 'wb') as file: file.write(fh)
到:
# download retrieved image from drive
item_ids = [i['id'] for i in items]
if len(item_ids) > 1:
print("Warning: multiple files exist with the same name. Using first file found.")
for i in item_ids:
request = drive.files().get_media(fileId=i)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
break
# delete retrieved image from drive
for i in item_ids:
try:
drive.files().delete(fileId=i).execute()
except errors.HttpError as error:
print(f'An error occured deleting file id <{i}>: {error}.')
# write bytearray to file
if item_ids != []:
with io.open(os.path.join(self.download_dir, f'{fname}.tif'), 'wb') as f:
fh.seek(0)
f.write(fh.read())