I have some hooks in place, and I thought I could decorate them with @ndb.tasklet in order to use async apis inside the hooks. e.g.
我有一些挂钩,我想我可以用@ndb来装饰它们。在钩子中使用异步api。如。
@classmethod
@ndb.tasklet
def _post_delete_hook(cls, key,future):
yield do_something_async()
This seemed to work, but every now and then I see "suspended generator" error for the code inside those hooks.
这似乎是可行的,但我偶尔会看到这些钩子中的代码出现“挂起生成器”错误。
Should I be using @ndb.synctasklet instead?
我应该使用@ndb吗?synctasklet呢?
An example of error:
一个错误的例子:
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>)
The code causing the error occasionally was:
导致错误的代码偶尔是:
t, d = yield (queue.add_async(task), queue.delete_tasks_async(taskqueue.Task(name=existing_task_name)))
Now that I've put @ndb.synctasklet it raises an actual exception.
现在我输入了@ndb。synctasklet引发了一个实际的异常。
1 个解决方案
#1
2
An ndb tasklet returns a future. If calling the tasklet results in an exception, the exception will only be raised if the future's get_result
method is called.
一个ndb微线程返回一个未来。如果调用微线程导致异常,那么只有在调用未来的get_result方法时才会引发异常。
ndb.synctasklet
automatically calls get_result
on the futures yielded by tasklets, causing exceptions to be raised if they occurred, rather than just logged.
ndb。synctasklet在tasklet生成的期货上自动调用get_result,在异常发生时引发异常,而不是仅仅记录日志。
For the error that you are seeing, you may be able to fix it by converting the UserRPCs returned by the taskqueue async methods to tasklets.
对于您正在看到的错误,您可以通过将taskqueue异步方法返回的UserRPCs转换为微线程来修复它。
This untested code is based on ndb.context.urlfetch
(link), which converts the UserRPC
produced by urlfetch.createRPC
into a Future
.
这个未测试的代码基于ndb.context。urlfetch (link),它转换urlfetch生成的UserRPC。createRPC变成一个未来。
@ndb.tasklet
def add_async(queue, **taskqueue_kwargs):
rpc = queue.add_async(**taskqueue_kwargs)
result = yield rpc
raise ndb.Return(result)
You would need to create a tasklet for each async method that you want to use, or you could extend the taskqueue class and make the async methods tasklets.
您需要为您想要使用的每个异步方法创建一个微线程,或者您可以扩展taskqueue类并使异步方法微线程。
#1
2
An ndb tasklet returns a future. If calling the tasklet results in an exception, the exception will only be raised if the future's get_result
method is called.
一个ndb微线程返回一个未来。如果调用微线程导致异常,那么只有在调用未来的get_result方法时才会引发异常。
ndb.synctasklet
automatically calls get_result
on the futures yielded by tasklets, causing exceptions to be raised if they occurred, rather than just logged.
ndb。synctasklet在tasklet生成的期货上自动调用get_result,在异常发生时引发异常,而不是仅仅记录日志。
For the error that you are seeing, you may be able to fix it by converting the UserRPCs returned by the taskqueue async methods to tasklets.
对于您正在看到的错误,您可以通过将taskqueue异步方法返回的UserRPCs转换为微线程来修复它。
This untested code is based on ndb.context.urlfetch
(link), which converts the UserRPC
produced by urlfetch.createRPC
into a Future
.
这个未测试的代码基于ndb.context。urlfetch (link),它转换urlfetch生成的UserRPC。createRPC变成一个未来。
@ndb.tasklet
def add_async(queue, **taskqueue_kwargs):
rpc = queue.add_async(**taskqueue_kwargs)
result = yield rpc
raise ndb.Return(result)
You would need to create a tasklet for each async method that you want to use, or you could extend the taskqueue class and make the async methods tasklets.
您需要为您想要使用的每个异步方法创建一个微线程,或者您可以扩展taskqueue类并使异步方法微线程。