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

Google App Engine中tmp目录存储Refresh Token的只读文件系统问题

解决Google App Engine上Flask应用访问tmp目录存储Token的问题

核心问题分析

  1. 路径错误:你代码中使用的相对路径tmp/token.json指向的是应用代码包内的tmp文件夹,而GAE标准环境下应用代码目录是只读的,只有系统根目录下的/tmp是临时可写目录。
  2. 授权流程不兼容:InstalledAppFlow.run_local_server()需要本地交互式授权,在GAE无服务器环境中无法执行,这也是后续无法生成/写入token的根本障碍之一。

解决方案(无需云存储)

方案一:预生成Token并通过环境变量加载

  1. 本地生成有效Token
    • 在本地运行你的代码,完成授权流程,生成token.json文件。
  2. 配置GAE环境变量
    • 打开Google Cloud控制台,进入你的GAE应用,在「设置」-「环境变量」中添加两个变量:
      • CREDENTIALS_JSON:填入本地credentials.json的完整内容
      • TOKEN_JSON:填入本地token.json的完整内容
  3. 修改认证代码
    将原代码中读取文件的逻辑替换为读取环境变量:
    import os
    import json
    from google.oauth2.credentials import Credentials
    from googleapiclient.discovery import build
    from googleapiclient.errors import HttpError
    from google.auth.transport.requests import Request
    
    SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
    
    def access_sheet():
        creds = None
        # 从环境变量加载预生成的token
        token_json = os.environ.get('TOKEN_JSON')
        if token_json:
            creds = Credentials.from_authorized_user_info(json.loads(token_json), SCOPES)
        
        # 处理token过期刷新
        if not creds or not creds.valid:
            if creds and creds.expired and creds.refresh_token:
                creds.refresh(Request())
            else:
                # 从环境变量加载credentials(仅本地运行时用,GAE上需提前生成token)
                creds_json = os.environ.get('CREDENTIALS_JSON')
                flow = InstalledAppFlow.from_client_config(json.loads(creds_json), SCOPES)
                raise RuntimeError("请先在本地完成授权生成token,再配置到环境变量")
        
        try:
            service = build('sheets', 'v4', credentials=creds)
            sheet = service.spreadsheets()
            return sheet
        except HttpError as err:
            print(err)
    

方案二:使用服务账号(更适合服务器端无交互场景)

服务账号无需用户交互式授权,直接通过密钥认证,是GAE这类服务器环境的最优解:

  1. 创建并配置服务账号
    • 在Google Cloud控制台创建服务账号,下载密钥JSON文件。
    • 将服务账号邮箱添加到目标Google Sheet的共享列表,赋予编辑权限。
  2. 配置GAE环境变量
    • 添加SERVICE_ACCOUNT_KEY变量,填入服务账号密钥JSON的完整内容。
  3. 修改认证代码
    import os
    import json
    from google.oauth2 import service_account
    from googleapiclient.discovery import build
    from googleapiclient.errors import HttpError
    
    SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
    
    def access_sheet():
        # 从环境变量加载服务账号密钥
        sa_key = json.loads(os.environ.get('SERVICE_ACCOUNT_KEY'))
        creds = service_account.Credentials.from_service_account_info(sa_key, scopes=SCOPES)
        
        try:
            service = build('sheets', 'v4', credentials=creds)
            sheet = service.spreadsheets()
            return sheet
        except HttpError as err:
            print(err)
    

临时路径修正(仅解决写权限,无法解决授权流程)

如果只是验证路径问题,可将代码中的路径替换为系统临时目录的绝对路径:

# 替换所有'tmp/xxx.json'为
os.path.join('/tmp', 'token.json')
os.path.join('/tmp', 'credentials.json')

注意:此方法无法解决InstalledAppFlow.run_local_server()在GAE上无法执行的问题,仅适用于已有预生成token的场景。

内容的提问来源于stack exchange,提问作者Piotrek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 08:42:38