如何将任何Google API服务对象传递到App Engine中的延迟任务?

时间:2017-03-21 13:56:43

标签: python google-app-engine google-api google-drive-api task-queue

我目前正在使用Drive v3 API开发App Engine应用程序,但此问题适用于大多数Google API。

由于Drive API在某些操作中有点慢,我想将每个文件处理分成不同的任务。为了做到这一点,我使用延迟库来避免序列化 - 反序列化参数。

主要参数是给定用户已经授权的Drive API服务对象(使用服务帐户和域范围权限)。

代码的简化代码段如下所示:

class Main(webapp2.RequestHandler):

    def get(self):

        # Authorize and get the Drive service 
        service = get_drive_service(keyfile, 'user@my-domain.com')

        # Iterate through all the (previously retrieved) file list
        for file_id in file_list:
            # Queue a new task by passing the function and its arguments
            deferred.defer(test_drive_service, service, file_id)


def test_drive_service(service, file_id):

    # Do a simple Drive operation
    response = service.files().get(fileId=file_id).execute()
    print response.get('name')
app.yaml 文件的

部分

handlers:
    - url: /_ah/queue/deferred
    script: google.appengine.ext.deferred.deferred.application
    login: admin

builtins:
    - deferred: on

如果我不使用 deferred.defer(),并直接调用test_drive_service()函数 ,则没有问题,我得到了正确的文件,信息正确。

但是,使用延迟库时,会引发以下错误:

HttpError: <HttpError 403 when requesting (...) returned "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.">

我的配额很好,所以没有达到每日限额。

可能导致此问题的原因是什么? 是否有任何其他特定方法可以将服务对象正确传递给任务队列?

修改

根据要求,这是我的身份验证流程:

def get_drive_service(keyfile, user_email):
    '''Builds and returns a Drive service object authorized with the service 
    account that acts on behalf of the given user.

    @param keyfile: generated JSON containing the service account details
    @param user_email: the email of the user.
    @return: Drive API service instance
    '''
    from oauth2client.service_account import ServiceAccountCredentials

    credentials = ServiceAccountCredentials.from_json_keyfile_dict(keyfile, SCOPES)

    credentials = credentials.create_delegated(user_email)

    http = credentials.authorize(httplib2.Http())
    service = discovery.build('drive', 'v3', http=http)

    return service

它基于Google Server-to-server OAuth 2.0 docs(“其他平台”部分),并且在直接调用函数时工作正常,而不是将其添加到任务队列。

2 个答案:

答案 0 :(得分:1)

问题可能是service未正确序列化/反序列化。如果反序列化的服务对象缺少其访问令牌,那将解释403 Quota for unauthenticated use

您有一个次要问题,您需要处理访问令牌在您的排队任务转向使用之前到期的可能性(这种情况会引发401状态)。

我不太了解AppEngine上的python建议一个简单的解决方案。我建议发布这是一个标记为appengine / python / google-oauth的新问题。

一个非简单的解决方案是创建一个新的端点,排队的任务可以调用该端点来获取访问令牌。

另一种方法是将auth流程移动到延迟任务中。由于您使用的是服务帐户,因此auth不需要任何用户交互。

答案 1 :(得分:0)

  

超出未经身份验证的使用的每日限制。继续使用需要注册

表示您未获得授权。您尚未向请求发送访问令牌。您的身份验证有些问题。

您正在使用哪个库我认为您需要找到更好的服务帐户示例。使用创建服务发送密钥文件对我来说不合适。