使用ms_graph模块从OneDrive下载文件遇ModuleNotFoundError求助
解决
ms_graph模块找不到的问题及OneDrive文件下载方案 错误原因
ms_graph并非公开的PyPI模块,无法通过pip安装。你仅安装了msal但代码依赖的ms_graph不存在,导致ModuleNotFoundError。
解决方案
方案1:基于msal手动实现token获取逻辑
直接用你已安装的msal库实现原代码中generate_access_token的功能,无需依赖不存在的ms_graph模块:
import os import requests from msal import PublicClientApplication # 定义Graph API基础端点 GRAPH_API_ENDPOINT = "https://graph.microsoft.com/v1.0" def generate_access_token(app_id, scopes): # 初始化公共客户端应用 client = PublicClientApplication(app_id) # 启动设备码授权流程(适合桌面端应用) flow = client.initiate_device_flow(scopes=scopes) if "user_code" not in flow: raise ValueError(f"创建设备流失败: {flow}") # 输出授权提示,用户需在浏览器中完成登录 print(flow["message"]) # 等待用户授权并获取token result = client.acquire_token_by_device_flow(flow) if "access_token" in result: return result else: raise Exception(f"获取token失败: {result.get('error')} - {result.get('error_description')}") # 配置参数 APP_ID = '<你的应用ID>' SCOPES = ['Files.Read'] save_location = os.getcwd() # 注意:这里需要填文件ID,不是文件夹ID file_ids = ['文件ID1', '文件ID2'] # 获取access token access_token = generate_access_token(APP_ID, scopes=SCOPES) headers = { 'Authorization': 'Bearer ' + access_token['access_token'] } # 批量下载文件 for file_id in file_ids: # 1. 获取文件名 response_file_info = requests.get( f"{GRAPH_API_ENDPOINT}/me/drive/items/{file_id}", headers=headers, params={'select': 'name'} ) if response_file_info.status_code != 200: print(f"文件 {file_id} 信息获取失败: {response_file_info.text}") continue file_name = response_file_info.json().get('name') if not file_name: print(f"无法获取文件 {file_id} 的名称") continue # 2. 下载文件内容 response_file_content = requests.get( f"{GRAPH_API_ENDPOINT}/me/drive/items/{file_id}/content", headers=headers ) if response_file_content.status_code == 200: with open(os.path.join(save_location, file_name), 'wb') as _f: _f.write(response_file_content.content) print(f"文件 {file_name} 下载完成") else: print(f"文件 {file_name} 下载失败: {response_file_content.text}")
方案2:使用官方Microsoft Graph Python SDK
官方SDK封装了更多细节,使用更便捷:
- 先安装SDK:
pip install msgraph-core
- 替换代码为:
import os from msgraph.core import GraphClient from msal import PublicClientApplication # 配置参数 APP_ID = '<你的应用ID>' SCOPES = ['Files.Read'] save_location = os.getcwd() file_ids = ['文件ID1', '文件ID2'] # 初始化客户端并获取token client = PublicClientApplication(APP_ID) flow = client.initiate_device_flow(scopes=SCOPES) print(flow["message"]) token_result = client.acquire_token_by_device_flow(flow) if "access_token" in token_result: # 创建Graph客户端 graph_client = GraphClient(credentials=token_result) for file_id in file_ids: # 获取文件名 file_info = graph_client.get(f'/me/drive/items/{file_id}', params={'select': 'name'}) if file_info.status_code != 200: print(f"文件 {file_id} 信息获取失败: {file_info.text}") continue file_name = file_info.json().get('name') if not file_name: print(f"无法获取文件 {file_id} 的名称") continue # 下载文件 file_content = graph_client.get(f'/me/drive/items/{file_id}/content') if file_content.status_code == 200: with open(os.path.join(save_location, file_name), 'wb') as _f: _f.write(file_content.content) print(f"文件 {file_name} 下载完成") else: print(f"文件 {file_name} 下载失败: {file_content.text}") else: print(f"获取token失败: {token_result.get('error')} - {token_result.get('error_description')}")
注意事项
- 确保你的Azure AD应用注册已启用设备码流:在应用注册的「认证」页面,添加「移动和桌面应用」平台,勾选「允许使用设备码流」。
file_ids需填写OneDrive文件的ID,而非文件夹ID。如果需要下载文件夹内所有文件,需先调用/me/drive/items/{folder_id}/children接口获取文件列表。
内容的提问来源于stack exchange,提问作者Daniele Spadola
相关产品推荐
相关产品推荐

