0

0

如何使用Python服务账户解决Google Sheets权限问题

霞舞

霞舞

发布时间:2025-07-23 16:04:17

|

379人浏览过

|

来源于php中文网

原创

如何使用python服务账户解决google sheets权限问题

本文详细介绍了如何利用Python服务账户创建Google Sheets并解决默认权限不足导致其他用户无法编辑的问题。核心解决方案在于通过Google Drive API,在创建电子表格后立即以编程方式为指定用户授予编辑或查看权限,确保服务账户创建的资源能够被目标用户正常访问和管理。

问题分析:服务账户创建的Google Sheets权限限制

当使用Python的gspread_asyncio库结合Google服务账户(Service Account)创建Google Sheets电子表格时,一个常见的问题是,虽然服务账户成功创建了电子表格并返回了链接,但其他用户(包括服务账户所关联的Google Cloud项目拥有者)却无法打开或编辑该表格,提示“没有权限”。

这背后的原因是:

  1. 所有权归属: 服务账户创建的资源,其默认所有者是该服务账户本身。
  2. 默认私有: Google Sheets的默认共享设置是私有的,即只有所有者和服务账户本身能够访问。
  3. 缺乏显式共享: 尽管服务账户可能属于某个Google Cloud项目,但它并不会自动将新创建的资源共享给项目中的其他用户或组。

因此,要解决这个问题,我们需要在电子表格创建后,显式地为目标用户或群组授予相应的访问权限。

解决方案概览:通过Google Drive API管理权限

解决此问题的关键在于利用Google Drive API。Google Drive API提供了丰富的功能来管理Google Drive中的文件和文件夹,包括设置共享权限。由于Google Sheets本质上是存储在Google Drive中的一种文件类型,我们可以通过Drive API来修改其权限设置。

立即学习Python免费学习笔记(深入)”;

具体步骤如下:

  1. 初始化Google Drive API客户端: 使用与gspread_asyncio相同的服务账户凭据初始化Google Drive API客户端。
  2. 定义权限: 构建一个权限对象,指定要共享的类型(用户、群组、域等)、角色(读取者、评论者、编辑者等)以及目标邮箱地址。
  3. 授予权限: 调用Drive API的permissions().create()方法,将定义的权限应用到新创建的电子表格上。

实现细节

以下是整合了权限管理功能的Python代码示例,它在创建Google Sheets并上传数据后,立即为指定用户授予编辑权限。

小羊标书
小羊标书

一键生成百页标书,让投标更简单高效

下载

1. 导入所需库

除了gspread_asyncio、io、csv和google.oauth2.service_account外,我们还需要导入googleapiclient.discovery来构建Google Drive API客户端。

from gspread_asyncio import AsyncioGspreadClientManager
import io
import csv
from google.oauth2 import service_account
from gspread.exceptions import SpreadsheetNotFound
from googleapiclient.discovery import build # 导入构建API客户端的模块

2. 初始化凭据与API客户端

确保服务账户凭据拥有足够的权限来访问Google Sheets API和Google Drive API。这意味着在创建服务账户时,需要为其分配包含https://www.googleapis.com/auth/drive和https://www.googleapis.com/auth/spreadsheets(或更宽泛的https://www.googleapis.com/auth)的OAuth 2.0 Scope。

async def upload_file_to_gsheets(credentials_path, csv_string, spreadsheet_name, target_user_email):
    try:
        # 定义所需的API范围
        scopes = [
            'https://www.googleapis.com/auth/spreadsheets', # 用于gspread操作
            'https://www.googleapis.com/auth/drive'        # 用于Google Drive API操作,包括权限管理
        ]
        credentials = service_account.Credentials.from_service_account_file(credentials_path, scopes=scopes)

        # 初始化gspread_asyncio客户端
        agcm = AsyncioGspreadClientManager(lambda: credentials)
        gc_client = await agcm.authorize()

        # 初始化Google Drive API客户端
        drive_service = build('drive', 'v3', credentials=credentials)

3. 创建或打开电子表格

这部分与原始代码相同,用于处理电子表格的创建或查找。

        try:
            spreadsheet = await gc_client.open(spreadsheet_name)
        except SpreadsheetNotFound:
            spreadsheet = await gc_client.create(spreadsheet_name)

        worksheet = await spreadsheet.get_worksheet(0)

        # 读取CSV数据并更新工作表
        csv_file = io.StringIO(csv_string)
        reader = csv.reader(csv_file)
        values_list = list(reader)
        await worksheet.update('A1', values_list)

4. 授予权限

这是解决问题的核心部分。我们定义一个权限对象,然后调用drive_service.permissions().create()方法。

        # 定义要授予的权限
        # 'type': 'user' 表示授予给特定用户
        # 'role': 'writer' 表示授予编辑权限。注意:服务账户不能将自身设置为其他用户的'owner'。
        # 'emailAddress': 替换为需要获得权限的用户的真实邮箱地址
        user_permission = {
            'type': 'user',
            'role': 'writer', 
            'emailAddress': target_user_email # 替换为实际用户的邮箱地址
        }

        # 授予权限
        # fileId: 电子表格的ID,可以通过spreadsheet.id获取
        # body: 包含权限信息的字典
        # fields: 指定返回的响应字段,这里只需要id
        drive_service.permissions().create(
            fileId=spreadsheet.id,
            body=user_permission,
            fields='id'
        ).execute() # 执行API请求

        spreadsheet_url = spreadsheet.url
        return spreadsheet_url

    except Exception as error:
        print(f"操作失败: {error}")
        return None

完整代码示例

将以上所有部分整合到一个完整的异步函数中:

from gspread_asyncio import AsyncioGspreadClientManager
import io
import csv
from google.oauth2 import service_account
from gspread.exceptions import SpreadsheetNotFound
from googleapiclient.discovery import build # 导入构建API客户端的模块

async def upload_file_to_gsheets_with_permissions(credentials_path: str, 
                                                 csv_string: str, 
                                                 spreadsheet_name: str, 
                                                 target_user_email: str) -> str:
    """
    使用服务账户创建Google Sheets,上传CSV数据,并为指定用户授予编辑权限。

    Args:
        credentials_path (str): 服务账户JSON密钥文件的路径。
        csv_string (str): 包含CSV数据内容的字符串。
        spreadsheet_name (str): 要创建或更新的电子表格名称。
        target_user_email (str): 需要授予编辑权限的用户的邮箱地址。

    Returns:
        str: 创建或更新的电子表格的URL,如果操作失败则返回None。
    """
    try:
        # 定义所需的API范围
        scopes = [
            'https://www.googleapis.com/auth/spreadsheets', # 用于gspread操作
            'https://www.googleapis.com/auth/drive'        # 用于Google Drive API操作,包括权限管理
        ]
        credentials = service_account.Credentials.from_service_account_file(credentials_path, scopes=scopes)

        # 1. 初始化gspread_asyncio客户端
        agcm = AsyncioGspreadClientManager(lambda: credentials)
        gc_client = await agcm.authorize()

        # 2. 初始化Google Drive API客户端
        drive_service = build('drive', 'v3', credentials=credentials)

        # 3. 创建或打开电子表格
        try:
            spreadsheet = await gc_client.open(spreadsheet_name)
            print(f"电子表格 '{spreadsheet_name}' 已存在,将进行更新。")
        except SpreadsheetNotFound:
            spreadsheet = await gc_client.create(spreadsheet_name)
            print(f"电子表格 '{spreadsheet_name}' 已创建。")

        # 获取第一个工作表并更新数据
        worksheet = await spreadsheet.get_worksheet(0)
        csv_file = io.StringIO(csv_string)
        reader = csv.reader(csv_file)
        values_list = list(reader)
        await worksheet.update('A1', values_list)
        print("数据已成功上传到电子表格。")

        # 4. 授予权限
        user_permission = {
            'type': 'user',
            'role': 'writer', # 'reader' for view-only, 'writer' for edit
            'emailAddress': target_user_email 
        }

        # 尝试授予权限,如果该用户已经有权限,可能会抛出错误,但通常不影响后续操作
        try:
            drive_service.permissions().create(
                fileId=spreadsheet.id,
                body=user_permission,
                fields='id'
            ).execute()
            print(f"已成功为用户 '{target_user_email}' 授予编辑权限。")
        except Exception as perm_error:
            print(f"授予权限失败或用户已有权限: {perm_error}")

        spreadsheet_url = spreadsheet.url
        print(f"电子表格URL: {spreadsheet_url}")
        return spreadsheet_url

    except Exception as error:
        print(f"操作失败: {error}")
        return None

# 示例用法 (需要运行在一个异步环境中,例如使用asyncio.run())
# import asyncio
# async def main():
#     credentials_path = 'path/to/your/service_account_key.json' # 替换为你的服务账户密钥文件路径
#     csv_data = "Header1,Header2\nValue1,Value2\nValue3,Value4"
#     spreadsheet_name = "MyAutomatedSheet"
#     target_email = "your_user_email@example.com" # 替换为你要共享的用户的邮箱

#     url = await upload_file_to_gsheets_with_permissions(credentials_path, csv_data, spreadsheet_name, target_email)
#     if url:
#         print(f"电子表格已创建并共享: {url}")
#     else:
#         print("操作未能完成。")

# if __name__ == "__main__":
#     asyncio.run(main())

注意事项

  1. API 启用: 确保您的Google Cloud项目中已启用 Google Sheets APIGoogle Drive API。您可以在Google Cloud Console的“API和服务” -> “库”中搜索并启用它们。
  2. 服务账户权限: 服务账户必须拥有足够的权限来创建电子表格和管理Drive文件权限。通常,授予包含Editor角色的权限,或者自定义角色以包含drive.files.create和drive.permissions.create等权限。
  3. Scopes: 在service_account.Credentials.from_service_account_file中,scopes参数必须包含https://www.googleapis.com/auth/drive,这是执行Drive API操作所必需的。
  4. target_user_email: 请务必将target_user_email替换为需要获得权限的真实用户的邮箱地址。如果邮箱地址不正确,权限授予将失败。
  5. 角色(Role):
    • 'writer':授予编辑权限。用户可以查看、编辑、评论文件。
    • 'reader':授予只读权限。用户只能查看文件。
    • 'owner':服务账户不能将自身创建的文件的所有权直接转移给另一个用户,即不能将role设置为'owner'。服务账户始终是其创建文件的所有者。
  6. 错误处理: 示例代码中包含基本的try-except块,但在生产环境中,您可能需要更细致的错误处理和日志记录。

总结

通过服务账户创建Google Sheets并自动解决权限问题,关键在于理解服务账户的默认行为以及如何利用Google Drive API来扩展其功能。通过在创建电子表格后立即编程授予指定用户权限,我们可以确保自动化流程生成的资源能够无缝地融入团队协作工作流中,提高效率并避免手动权限设置的繁琐。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
console接口是干嘛的
console接口是干嘛的

console接口是一种用于在计算机命令行或浏览器开发工具中输出信息的工具,提供了一种简单的方式来记录和查看应用程序的输出结果和调试信息。本专题为大家提供console接口相关的各种文章、以及下载和课程。

419

2023.08.08

console.log是什么
console.log是什么

console.log 是 javascript 函数,用于在浏览器控制台中输出信息,便于调试和故障排除。想了解更多console.log的相关内容,可以阅读本专题下面的文章。

537

2024.05.29

http与https有哪些区别
http与https有哪些区别

http与https的区别:1、协议安全性;2、连接方式;3、证书管理;4、连接状态;5、端口号;6、资源消耗;7、兼容性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2836

2024.08.16

PHP 命令行脚本与自动化任务开发
PHP 命令行脚本与自动化任务开发

本专题系统讲解 PHP 在命令行环境(CLI)下的开发与应用,内容涵盖 PHP CLI 基础、参数解析、文件与目录操作、日志输出、异常处理,以及与 Linux 定时任务(Cron)的结合使用。通过实战示例,帮助开发者掌握使用 PHP 构建 自动化脚本、批处理工具与后台任务程序 的能力。

63

2025.12.13

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

3

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

21

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

108

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

51

2026.03.04

Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

89

2026.03.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 4.8万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号