You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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封装了更多细节,使用更便捷:

  1. 先安装SDK:
pip install msgraph-core
  1. 替换代码为:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 02:12:14