Google 的 API 通过 python 的长期超时问题?
Chronic timeout issue with Google's API via python?
我正在开发一个小网络应用程序来帮助我管理我的 gmail。我已经通过 Google 的 API 使用以下功能使用我通过 django-allauth
收到的 OAuth 令牌对其进行了设置。
import google.oauth2.credentials
from .choices import GMAIL
from allauth.socialaccount.models import SocialToken, SocialAccount
from apiclient.discovery import build
def get_credentials(user):
account = SocialAccount.objects.get(user=user.id)
token = SocialToken.objects.get(app=GMAIL, account=account).token
credentials = google.oauth2.credentials.Credentials(token)
service = build('gmail', 'v1', credentials=credentials)
return service
这似乎有时有效,但不幸的是,它不是很可靠。它在 build()
函数中经常超时,只有大约三分之一的时间会成功。我想知道是什么导致了这种行为,是否有更可靠的方法来访问 API?
我从 these docs 中找到了以下 AuthorizedSession
class:
from google.auth.transport.requests import AuthorizedSession
authed_session = AuthorizedSession(credentials)
response = authed_session.request(
'GET', 'https://www.googleapis.com/storage/v1/b')
但我不知道如何将它变成与 Google 一起使用的那种对象 API:
def get_labels(user):
service = get_credentials(user)
results = service.users().labels().list(userId='me').execute()
labels = results.get('labels', [])
return labels
不幸的是,Google's docs 建议使用我希望避免的已弃用的软件包。
这是我第一次真正使用 OAuth 强制 API。有人有什么建议吗?
编辑:我在我的 Macbook 上尝试后发布。我也在我的 Windows 机器上试过了,它工作得更稳定,但每次只需要大约 20 秒就可以完成 build()
。我觉得我做错了什么。
在我最终将刷新令牌添加到组合中后,今天早上效果好多了。也许它的缺席导致了另一端的一些问题。我会继续测试,但现在一切正常:
这是我的完整解决方案:
import google.oauth2.credentials
from google.auth.transport.requests import Request
from apiclient import errors, discovery
from myproject.settings import GMAIL_CLIENT_API_KEY, GMAIL_CLIENT_API_SECRET
def get_credentials(user):
token_set = user.socialaccount_set.first().socialtoken_set.first()
token = token_set.token
refresh_token = token_set.token_secret
credentials = google.oauth2.credentials.Credentials(
token,
refresh_token=refresh_token,
client_id=GMAIL_CLIENT_API_KEY,
client_secret=GMAIL_CLIENT_API_SECRET,
token_uri= google.oauth2.credentials._GOOGLE_OAUTH2_TOKEN_ENDPOINT,
)
if credentials.expired:
request = Request()
credentials.refresh(request)
service = discovery.build('gmail', 'v1', credentials=credentials)
return service
如您所见,我将 API 密钥添加到我的设置文件中并在此处引用它们。昨天我在查看源文件时偶然发现了 token_uri
。 refresh_token
是找到时间最长的一块。
好消息是 django-allauth 会将刷新令牌保存到 token_secret
列下的 SocialToken
模型。但是,只有在您的设置中包含以下内容时才会执行此操作:
SOCIALACCOUNT_PROVIDERS = {
'google': {
'SCOPE': [
'profile',
'email',
'https://www.googleapis.com/auth/gmail.labels',
'https://www.googleapis.com/auth/gmail.modify'
],
'AUTH_PARAMS': {
'access_type': 'offline',
}
}
}
具体来说,AUTH_PARAMS
中的access_type
必须设置为'offline'
according to the docs。
现在,如果您在实施此更改之前连接了您的帐户,这仍然会给您带来麻烦,因此您还需要通过 Google permissions to obtain a new refresh token. More about that can be found in this question.
撤销对您的应用程序的访问权限
我不确定这是否是 proper/intended 执行此操作的方法,但在 Google 更新他们的 Django 文档之前,此方法至少应该可以用于测试目的。
我正在开发一个小网络应用程序来帮助我管理我的 gmail。我已经通过 Google 的 API 使用以下功能使用我通过 django-allauth
收到的 OAuth 令牌对其进行了设置。
import google.oauth2.credentials
from .choices import GMAIL
from allauth.socialaccount.models import SocialToken, SocialAccount
from apiclient.discovery import build
def get_credentials(user):
account = SocialAccount.objects.get(user=user.id)
token = SocialToken.objects.get(app=GMAIL, account=account).token
credentials = google.oauth2.credentials.Credentials(token)
service = build('gmail', 'v1', credentials=credentials)
return service
这似乎有时有效,但不幸的是,它不是很可靠。它在 build()
函数中经常超时,只有大约三分之一的时间会成功。我想知道是什么导致了这种行为,是否有更可靠的方法来访问 API?
我从 these docs 中找到了以下 AuthorizedSession
class:
from google.auth.transport.requests import AuthorizedSession
authed_session = AuthorizedSession(credentials)
response = authed_session.request(
'GET', 'https://www.googleapis.com/storage/v1/b')
但我不知道如何将它变成与 Google 一起使用的那种对象 API:
def get_labels(user):
service = get_credentials(user)
results = service.users().labels().list(userId='me').execute()
labels = results.get('labels', [])
return labels
不幸的是,Google's docs 建议使用我希望避免的已弃用的软件包。
这是我第一次真正使用 OAuth 强制 API。有人有什么建议吗?
编辑:我在我的 Macbook 上尝试后发布。我也在我的 Windows 机器上试过了,它工作得更稳定,但每次只需要大约 20 秒就可以完成 build()
。我觉得我做错了什么。
在我最终将刷新令牌添加到组合中后,今天早上效果好多了。也许它的缺席导致了另一端的一些问题。我会继续测试,但现在一切正常:
这是我的完整解决方案:
import google.oauth2.credentials
from google.auth.transport.requests import Request
from apiclient import errors, discovery
from myproject.settings import GMAIL_CLIENT_API_KEY, GMAIL_CLIENT_API_SECRET
def get_credentials(user):
token_set = user.socialaccount_set.first().socialtoken_set.first()
token = token_set.token
refresh_token = token_set.token_secret
credentials = google.oauth2.credentials.Credentials(
token,
refresh_token=refresh_token,
client_id=GMAIL_CLIENT_API_KEY,
client_secret=GMAIL_CLIENT_API_SECRET,
token_uri= google.oauth2.credentials._GOOGLE_OAUTH2_TOKEN_ENDPOINT,
)
if credentials.expired:
request = Request()
credentials.refresh(request)
service = discovery.build('gmail', 'v1', credentials=credentials)
return service
如您所见,我将 API 密钥添加到我的设置文件中并在此处引用它们。昨天我在查看源文件时偶然发现了 token_uri
。 refresh_token
是找到时间最长的一块。
好消息是 django-allauth 会将刷新令牌保存到 token_secret
列下的 SocialToken
模型。但是,只有在您的设置中包含以下内容时才会执行此操作:
SOCIALACCOUNT_PROVIDERS = {
'google': {
'SCOPE': [
'profile',
'email',
'https://www.googleapis.com/auth/gmail.labels',
'https://www.googleapis.com/auth/gmail.modify'
],
'AUTH_PARAMS': {
'access_type': 'offline',
}
}
}
具体来说,AUTH_PARAMS
中的access_type
必须设置为'offline'
according to the docs。
现在,如果您在实施此更改之前连接了您的帐户,这仍然会给您带来麻烦,因此您还需要通过 Google permissions to obtain a new refresh token. More about that can be found in this question.
撤销对您的应用程序的访问权限我不确定这是否是 proper/intended 执行此操作的方法,但在 Google 更新他们的 Django 文档之前,此方法至少应该可以用于测试目的。