Google Drive API报错:'Credentials'对象无'request'属性
解决Google Drive API上传时的AttributeError问题
问题背景
为GUI添加Google Drive同步功能,支持用户上传重要文件夹至云端备份,遵循官方API实现时触发错误,相关问题搜索无匹配案例。
错误回溯
File "D:\Programming Projects\Projects-Manager\main.py", line 96, in <module> id_ = upload_zip(zip_created_path, cred_path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\Programming Projects\Projects-Manager\google_drive\drive.py", line 51, in upload_zip fields='id').execute() ^^^^^^^^^ File "D:\Programming Projects\Projects-Manager\env\Lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper return wrapped(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\Programming Projects\Projects-Manager\env\Lib\site-packages\googleapiclient\http.py", line 902, in execute _, body = self.next_chunk(http=http, num_retries=num_retries) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\Programming Projects\Projects-Manager\env\Lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper return wrapped(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\Programming Projects\Projects-Manager\env\Lib\site-packages\googleapiclient\http.py", line 1007, in next_chunk resp, content = _retry_request( ^^^^^^^^^^^^^^^ File "D:\Programming Projects\Projects-Manager\env\Lib\site-packages\googleapiclient\http.py", line 191, in _retry_request resp, content = http.request(uri, method, *args, **kwargs) ^^^^^^^^^^^^ AttributeError: 'Credentials' object has no attribute 'request'
引发错误的代码
import os.path from pathlib import 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 from googleapiclient.http import MediaFileUpload SCOPES = ["https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/drive.metadata", "https://www.googleapis.com/auth/drive.readonly", "https://www.googleapis.com/auth/drive.metadata.readonly"] drive_folder = "google_drive" def get_token(cred_path): cred_path = Path(cred_path) cred = None token_file_path = Path(Path.cwd(), drive_folder, "token.json") if token_file_path.exists(): cred = Credentials.from_authorized_user_file(str(token_file_path), SCOPES) if not cred or not cred.valid: if cred and cred.expired and cred.refresh_token: cred.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file( str(cred_path), SCOPES ) cred = flow.run_local_server(port=0) with open(token_file_path, 'w') as file: file.write(cred.to_json()) return cred return cred def upload_zip(zip_created_path, credential_path): cred = get_token(credential_path) zip_name = os.path.basename(zip_created_path) try: service = build("drive", 'v3', cred) file_metadata = {"name": zip_name, "mimeType": "application/zip"} media = MediaFileUpload(zip_created_path, mimetype="application/zip", resumable=True) file = service.files().create(body=file_metadata, media_body=media, fields='id').execute() os.remove(zip_created_path) return file.get('id') except HttpError as error: print(F'An error occurred: {error}') return
解决方案
错误根源是调用build方法时参数传递错误:直接将Credentials对象作为位置参数传入,而build的第三个位置参数是http(要求HTTP客户端对象),导致后续代码尝试调用Credentials的request方法触发异常。
核心修正
将build调用中的位置参数改为关键字参数credentials=cred:
service = build("drive", 'v3', credentials=cred)
可选逻辑优化
调整get_token函数的返回逻辑,确保无论分支走向都统一返回凭据:
def get_token(cred_path): cred_path = Path(cred_path) cred = None token_file_path = Path(Path.cwd(), drive_folder, "token.json") if token_file_path.exists(): cred = Credentials.from_authorized_user_file(str(token_file_path), SCOPES) if not cred or not cred.valid: if cred and cred.expired and cred.refresh_token: cred.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file( str(cred_path), SCOPES ) cred = flow.run_local_server(port=0) with open(token_file_path, 'w') as file: file.write(cred.to_json()) # 统一在此返回,避免分支内return导致的逻辑混乱 return cred
内容的提问来源于stack exchange,提问作者SAVEPALASTINE
相关产品推荐
相关产品推荐

