Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何将任何GoogleAPI服务对象传递给AppEngine中的延迟任务?_Python_Google App Engine_Google Api_Google Drive Api_Task Queue - Fatal编程技术网

Python 如何将任何GoogleAPI服务对象传递给AppEngine中的延迟任务?

Python 如何将任何GoogleAPI服务对象传递给AppEngine中的延迟任务?,python,google-app-engine,google-api,google-drive-api,task-queue,Python,Google App Engine,Google Api,Google Drive Api,Task Queue,我目前正在使用DriveV3API开发一个应用程序引擎应用程序,但这个问题适用于大多数Google API 由于驱动器API在某些操作中速度较慢,我想将每个文件处理分为不同的任务。为此,我使用延迟库来避免序列化反序列化参数 主要参数是给定用户的已授权驱动器API服务对象(使用服务帐户和域范围权限) 代码的简化片段如下所示: class Main(webapp2.RequestHandler): def get(self): # Authorize and get th

我目前正在使用DriveV3API开发一个应用程序引擎应用程序,但这个问题适用于大多数Google API

由于驱动器API在某些操作中速度较慢,我想将每个文件处理分为不同的任务。为此,我使用延迟库来避免序列化反序列化参数

主要参数是给定用户的已授权驱动器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.deferred()
,并直接调用test\u drive\u service()函数,则没有问题,我正确获得了正确的文件和信息

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

HttpError: <HttpError 403 when requesting (...) returned "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.">
它基于(部分“其他平台”),并且在直接调用函数时工作正常,而不是将其添加到任务队列中

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

意味着你没有被授权。您尚未随请求发送访问令牌。您的身份验证出现问题


我认为你需要找到一个更好的服务帐户示例。在创建服务时发送密钥文件在我看来并不合适

问题可能是
服务
未正确序列化/反序列化。如果反序列化的服务对象缺少其访问令牌,这将解释未经身份验证使用的
403配额

第二个问题是,您需要处理访问令牌在排队的任务开始使用之前过期的可能性(这种情况将引发401状态)

我对AppEngine上的python了解不够,无法提出一个简单的解决方案。我建议发布这个新问题,标记为appengine/python/googleoauth

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


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

谢谢您的回复,但正如我所提到的,驱动器服务在直接调用函数时按预期工作,但在延迟时显示错误。我正在使用
from\u json\u keyfile\u dict()
函数(在Python中)检索凭据,以便稍后授权和构建服务。如果您愿意,我可以编辑问题以添加身份验证流,但我认为这不是问题所在。由于某些原因,延迟库进行的内部序列化-反序列化正在取消对用户/服务的身份验证。我认为添加身份验证流是一个好主意。不管是什么,这就是错误的意思。您没有身份验证。这也可能仅仅是因为您没有将访问令牌应用于您正在发出的请求。检查服务,看看它是否真的获得了访问令牌。好的,添加了。但正如我之前指出的,授权流在除此之外的任何其他场景(延迟/使用任务队列)中都能正常工作。我的主要猜测也是序列化-反序列化不好。我在引用中发现了这两个可能相关的方法:。延迟库实际上会对传递的参数进行pickle处理,所以我猜这些方法是在内部调用的。将身份验证流移动到任务中是可行的,但由于文件数量太多,它将花费太多的配额。我需要研究端点解决方案。也许从Datastore/Memchache存储和检索服务……这是您需要传递的访问令牌——memcache将是一个不错的选择。同样,我不熟悉python库,但我希望能够实例化一个服务,然后注入一个访问令牌。无论哪种方式,都要确保延迟的任务能够处理过期的访问令牌。
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