我有一个 POST
方法,它调用一些 tasklet。这些 tasklet 确实有 yield ,我的代码中确实有一些 x.put_async()
。所以我不希望它在所有异步内容完成之前返回。所以我用 @ndb.tasklet
修饰了我所有的 tasklet,它们只是一些小函数。此外,在我的 POST
方法之上,我有:
@ndb.toplevel
def post(self):
但是,在 documentation它指出:
But if a handler method uses yield, that method still needs to be wrapped in another decorator, @ndb.synctasklet; otherwise, it will stop executing at the yield and not finish.
我的方法确实有收获。它已经包装在@ndb.tasklet 中。我是将其替换为 @ndb.synctasklet 还是两者都使用(如果是,我将如何同时使用两者)?
另请参阅 this thread这有一定的相关性。我也注意到一个问题,即我的请求将在没有任何输出的情况下返回,但无法重现。它每 15 分钟左右持续使用一次。我只有 app = ndb.toplevel(webapp2.WSGIApplication([..])
,但现在我已经将 @ndb.toplevel
添加到主 POST
方法,但问题仍然存在。
我是否应该将 @ndb.tasklet
放在也只有 put_async()
的方法之上? (为了安全起见,我是否应该将它放在每个方法之上?这样做有什么缺点?)
最佳答案
关于处理程序和使用@ndb.toplevel 和@ndb.synctasklet: 我的理解是,您需要在处理程序上同时使用 @ndb.synctasklet 和 @ndb.toplevel。所有子任务只需要 @ndb.tasklet 装饰器。例如
class Foo(ndb.Model):
name = ndb.StringProperty()
@ndb.tasklet
def my_async(self):
....
#do something else that yields
raise ndb.Return("some result")
@ndb.toplevel
@ndb.synctasklet
def post(self):
foo = Foo(name="baz")
yield foo.put_async()
yield foo.my_async()
....
但是。看着 source ,看起来 @ndb.toplevel 实际上是一个 synctasklet:
def toplevel(func):
"""A sync tasklet that sets a fresh default Context.
Use this for toplevel view functions such as
webapp.RequestHandler.get() or Django view functions.
"""
在处理程序中使用 yields 运行一个小测试并用 @ndb.toplevel 装饰似乎仍然有效,而且您似乎可以从处理程序中删除 @ndb.synctasklet。
关于是否应该在调用 put_async() 的方法中包含 @ndb.tasklet: 如果你没有在 put_async() 上产生,那么你不需要在周围的方法中包含 @ndb.tasklet(@ndb.toplevel 将处理从 put_async() 获取结果)
关于python - 在 Google App Engine 中使用 @ndb.tasklet 或 @ndb.synctasklet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12256093/