问题描述
我知道标题太不可思议了,对此我深表歉意.我遇到的难题是 gspread 使用Session和适用于Python的Google API客户端库使用HTTPLib2.我有一个与Google API客户端一起使用的服务帐户,并且希望采用经过身份验证的httplib2.Http()
实例并将其包装起来,以便gspread可以像Session对象一样使用它.
I know the title is a big wonky and I apologize for that. The dilemma I have is that gspread uses Session and the Google APIs client library for Python uses HTTPLib2. I have a service account that I have working with the Google API client and want to take the authenticated httplib2.Http()
instance and wrap it so that gspread can use it like a Session object.
更新:已通过更新103 固定为gspread.基于下面Jay Lee的出色回答,以下是在Python 2.7中使用服务帐户初始化gspread Client
的方法(您将需要替换/path/to/service-account.p12
并设置sa_id
):
UPDATE: Fixed with update 103 to gspread. Based on Jay Lee's awesome answer below, here's how to initialize the gspread Client
with a service account in Python 2.7 (you will need to replace /path/to/service-account.p12
and set sa_id
):
import gspread
from oauth2client.client import SignedJwtAssertionCredentials
from apiclient.discovery import build
# ...
with open('/path/to/service-account.p12') as f: sa_key = f.read()
credentials = SignedJwtAssertionCredentials(
sa_id, sa_key, 'https://spreadsheets.google.com/feeds')
http = httplib2.Http()
http = credentials.authorize(http)
build('drive', 'v2', http = http)
access_token = http.request.credentials.access_token
gspread_auth_headers = {'Authorization' : 'Bearer %s' % access_token}
gspread_session = gspread.httpsession.HTTPSession(headers=gspread_auth_headers)
fakeauth = ('[email protected]', 'notmypassword')
client = gspread.Client(fakeauth, http_session=gspread_session)
# https://github.com/burnash/gspread/issues/103
if False == hasattr(client, "session"):
client = gspread.Client(fakeauth)
client.session = gspread_session
现在,您可以像平常一样使用client
. 哇!
Now you can use client
as you normally would. Whew!
推荐答案
快速浏览gspread表示它正在使用旧的ClientLogin身份验证协议,该协议已被弃用.但是您应该能够从httplib2.Http()实例中获取访问令牌,并将相同的标头应用于gspread会话(有效地使gspread也使用OAuth 2.0):
A quick look at gspread indicates it's using the old ClientLogin authentication protocol which is deprecated. But you should be able to grab the access token from the httplib2.Http() instance and apply the same header to the gspread session (effectively getting gspread to use OAuth 2.0 also):
http = <<<Your existing, authenticated httplib2.Http() object)>>>
access_token = http.request.credentials.access_token
gspread_auth_headers = {'Authorization': 'Bearer %s' % access_token}
gspread_session = gspread.httpsession.HTTPSession(headers=gspread_auth_headers)
my_gspread = gspread.Client(auth=('[email protected]', 'notmypassword'), http_session=gspread_session)
[email protected]
和notmypassword
在这里是随机字符串,仅因为gspread.Client期望auth是传递给它的元组,所以它们才是必需的,除非您调用my_gspread.login(),否则它们不会传递给Google. (您不会).
[email protected]
and notmypassword
are random strings here, they're only needed because gspread.Client expects auth to be a tuple passed to it and they won't be passed to Google unless you call my_gspread.login() (which you won't).
您将需要当心并捕获过期的access_tokens.如果gspread引发有关无效令牌的错误,则应捕获该错误,调用http.request.credentials.refresh()获取新的访问令牌,然后使用新令牌重新创建gspread会话.
You will need to watch out for and catch expired access_tokens. If gspread throws an error about invalid tokens, you should catch it, call http.request.credentials.refresh() to get a new access token and then recreate the gspread session with the fresh token.
这篇关于一个如何将HTTPLib2实例转换/包装为会话?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!