使用ServiceAccount调用Google Drive API的文件列表与上传异常咨询
问题描述
我想编写一个简单的Python脚本,递归列出指定文件夹ID下的文件/文件夹,但遇到了以下问题:
- 将根文件夹ID设为“root”(本应对应Google Drive的“My Drive”根目录),首次运行列表脚本时未返回任何结果。
- 测试上传脚本时,将父ID改为“root”,期望在“My Drive”下创建文件夹/文件,脚本运行无报错,但在“My Drive”中找不到上传的内容;再次运行列表脚本,仅返回该上传脚本创建的文件夹和文件,看不到My Drive里的其他内容。
请问:
- 这种情况为何会发生?上传的文件夹/文件存放在哪里?
- 为何我在My Drive中看不到它们?
- 为何脚本仅列出通过脚本上传的文件,而非My Drive中的其余内容?
列表脚本代码
from googleapiclient.discovery import build from google.oauth2 import service_account # Set up the Google Drive API service scope = ['https://www.googleapis.com/auth/drive'] service_account_json_key = 'credentials.json' credentials = service_account.Credentials.from_service_account_file( filename=service_account_json_key, scopes=scope) service = build('drive', 'v3', credentials=credentials) # Function to list files and folders recursively def list_files_and_folders(folder_id, indent=""): results = service.files().list( q=f"'{folder_id}' in parents", fields="files(id, name, mimeType)").execute() items = results.get('files', []) if not items: print(indent + "No files or folders found.") else: for item in items: print(indent + f"{item['name']} ({item['id']}) - {item['mimeType']}") if item['mimeType'] == 'application/vnd.google-apps.folder': list_files_and_folders(item['id'], indent + " ") # Call the function to list files and folders starting from the specified folder ID root_folder_id = 'root' print(f"Listing files and folders recursively from root folder (ID: {root_folder_id}):") list_files_and_folders(root_folder_id)
上传脚本代码
from googleapiclient.discovery import build from googleapiclient.http import MediaFileUpload from google.oauth2 import service_account # Replace 'FOLDER_NAME' with the name you want to give your new folder folder_name = 'Test Upload 2' # setup google drive credentials = service_account.Credentials.from_service_account_file( 'credentials.json', scopes=['https://www.googleapis.com/auth/drive'] ) service = build("drive", "v3", credentials=credentials) folder_metadata = { 'name': folder_name, "parents": ['root'], 'mimeType': 'application/vnd.google-apps.folder' } # create folder new_folder = service.files().create(body=folder_metadata).execute() #upload file inside the folder file_metadata = {'name': 'image2.webp', 'parents': [new_folder['id']]} media = MediaFileUpload('image2.webp') file = service.files().create(body=file_metadata, media_body=media).execute() # list the file inside of the folder results = service.files().list(q=f"'{new_folder['id']}' in parents", fields="files(name)").execute() items = results.get('files', []) print(f"Files inside the folder , {items}")
问题解答
1. 原因与文件存储位置
你使用的是**服务账号(Service Account)**身份调用Google Drive API,服务账号拥有独立的Google Drive存储空间,和你个人账号的“My Drive”是完全独立的两个空间。
当你把父ID设为“root”时,这个“root”对应的是服务账号自己的Drive根目录,而非你个人账号的“My Drive”。上传的文件/文件夹都存在服务账号的独立Drive空间里,和你的个人Drive无关。
2. 个人My Drive看不到的原因
服务账号的Drive是独立隔离的,默认不会与你的个人账号共享任何内容。所以你在自己的“My Drive”里看不到服务账号上传的文件,除非手动给服务账号上传的内容设置共享权限,将你的个人账号添加为协作者。
3. 脚本仅列出自身上传内容的原因
列表脚本使用服务账号身份,只能访问服务账号自己Drive空间内的内容。你个人“My Drive”里的文件不在服务账号的存储空间中,自然无法被列出;而脚本上传的内容都存在服务账号的Drive里,所以能被正常读取。
补充解决方案
如果需要让脚本访问你个人账号的“My Drive”内容,有两种可行方式:
- 共享文件夹:将你个人“My Drive”中的目标文件夹共享给服务账号的邮箱(在
credentials.json文件的client_email字段中),然后在脚本中使用该共享文件夹的ID代替“root”。 - 改用OAuth 2.0授权:替换服务账号授权流程为OAuth 2.0授权,让脚本以你个人账号的身份访问Drive API,这样就能直接操作你的“My Drive”。
内容的提问来源于stack exchange,提问作者x0100
相关产品推荐
相关产品推荐

