我有一些钩子,我想我可以使用@ndb.tasklet来装饰它们,以便在钩子中使用异步apis。 e.g。
@classmethod
@ndb.tasklet
def _post_delete_hook(cls, key,future):
yield do_something_async()
这似乎可以正常工作,但我偶尔会看到这些挂钩内的代码出现“暂停生成器”错误。
我应该使用@ ndb.synctasklet吗?
错误的一个例子:
suspended generator _post_put_hook(data_field.py:112) raised TypeError(Expected Future, received <class 'google.appengine.api.apiproxy_stub_map.UserRPC'>: <google.appengine.api.apiproxy_stub_map.UserRPC object at 0x09AA00B0>)
偶尔导致错误的代码是:
t, d = yield (queue.add_async(task), queue.delete_tasks_async(taskqueue.Task(name=existing_task_name)))
现在我已经放了@ndb.synctasklet它引发了一个实际的异常。
答案 0 :(得分:2)
ndb tasklet返回未来。如果调用tasklet导致异常,则只有在调用将来的get_result
方法时才会引发异常。
ndb.synctasklet
会自动调用由tasklet产生的期货get_result
,如果发生异常则会引发异常,而不是仅记录。
对于您看到的错误,您可以通过将taskqueue异步方法返回的UserRPC转换为tasklet来修复它。
此未经测试的代码基于ndb.context.urlfetch
(link),可将UserRPC
生成的urlfetch.createRPC
转换为Future
。
@ndb.tasklet
def add_async(queue, **taskqueue_kwargs):
rpc = queue.add_async(**taskqueue_kwargs)
result = yield rpc
raise ndb.Return(result)
您需要为要使用的每个异步方法创建一个tasklet,或者您可以扩展taskqueue类并生成异步方法tasklet。