【问题标题】:Chronic timeout issue with Google's API via python?通过 python 使用 Google API 的慢性超时问题?
【发布时间】:2019-03-31 09:51:13
【问题描述】:

我正在开发一个小型网络应用程序来帮助我管理我的 gmail。我已经使用通过django-allauth 收到的OAuth 令牌通过Google 的API 使用以下功能进行了设置。

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 类:

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()。我觉得我做错了什么。

【问题讨论】:

    标签: django google-api google-oauth django-allauth google-python-api


    【解决方案1】:

    在我终于将刷新令牌添加到组合中后,今天早上效果好多了。也许它的缺席在另一端引起了一些问题。我将继续测试,但现在一切正常:

    这是我的完整解决方案:

    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_urirefresh_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 撤销对您的应用程序的访问权限以获取新的刷新令牌。更多相关信息请见in this question

    我不确定这是否是正确/有意的做法,但在 Google 更新他们的 Django 文档之前,这种方法至少应该可以用于测试目的。

    【讨论】:

    • 跟进 - 我至少将把它留给我自己参考,但这并没有最终解决最初的问题。对于似乎导致此问题的特定本地网络,我遇到了某种问题。
    猜你喜欢
    • 2018-06-14
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    • 2017-07-29
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    • 2022-08-04
    相关资源
    最近更新 更多