当授权 API 会话或凭据刷新请求任一需要代理时,请同时配置 gspread 的授权 API 会话和凭据刷新的请求传输:

import requests
import gspread
from google.auth.transport.requests import AuthorizedSession, Request

routes = {
    'http': 'http://proxy.example:8080',
    'https': 'http://proxy.example:8080',
}
token_session = requests.Session()
token_session.proxies.update(routes)

session = AuthorizedSession(
    credentials,
    auth_request=Request(session=token_session),
)
session.proxies.update(routes)
client = gspread.Client(auth=credentials, session=session)

这里使用 gspread 6 的 Client 接口,配合外部传入的会话和应用已有的凭据。它配置的是传输层,而不是电子表格权限或 OAuth 范围。对于允许的公开路由上的公开 API 与令牌端点,请从 HTTP 代理列表 中选择一个未认证的 HTTP 候选,填入 routes 映射。更换中间层时,要保证两个会话都不残留任何已保存的代理账号。

AuthorizedSession 会为 API 请求附加凭据,并且能够刷新凭据。若不传 auth_request,google-auth 可能为该流量另建一个 Requests 会话。授权会话上的代理默认值不会配置那个被独立创建的会话。

上面的 Request 适配器正是有意提供第二条通路。使用期间请保留两个会话,随后在各自应用范围结束时关闭由外部持有的会话。

这些都是 Session 的默认值,因此 Requests 的环境变量合并仍可能影响它们。需要固定路由时,要考虑到从环境继承的代理输入。

用失败的 URL 区分电子表格拒绝、代理挑战与凭据端点故障。缓存中的访问令牌可能让 API 调用直接成功,从而完全不触发刷新。

相关文章