[英]How to override an async NDB method and write your own tasklet
我正在嘗試掌握 NDB 引入的異步操作,我想使用@ndb.tasklet
來異步我的一些工作。
簡單的例子是在覆蓋的 get_or_insert_async 中生成get_or_insert_async
這是處理事情的正確方法嗎? 這里有什么可以改進的?
@classmethod
@ndb.tasklet
def get_or_insert_async(cls, *args):
id = cls.make_string_id(*args)
model = yield super(MyModel, cls).get_or_insert_async(id)
raise ndb.Return(model)
另一個例子是以扇出的方式在循環中做一些事情。 這個對嗎?
@classmethod
@ndb.tasklet
def do_stuff(cls, some_collection):
@ndb.tasklet
def internal_tasklet(data):
do_some_long_taking_stuff(data)
id = make_stuff_needed_for_id(data)
model = yield cls.get_or_insert_async(id)
model.long_processing(data)
yield model.put_async()
raise ndb.Return(None)
for data in some_collection:
# will it parallelise internal_tasklet execution?
yield internal_tasklet(data)
raise ndb.Return(None)
編輯:
正如對整個概念的理解, yields
在這里提供一個Future
對象,然后並行收集(在可能的情況下)並異步執行。 我對么?
在 Nick 的提示之后(是你的意思嗎?):
@classmethod
@ndb.tasklet
def do_stuff(cls, some_collection):
@ndb.tasklet
def internal_tasklet(data):
do_some_long_taking_stuff(data)
id = make_stuff_needed_for_id(data)
model = yield cls.get_or_insert_async(id)
model.long_processing(data)
raise ndb.Return(model) # change here
models = []
for data in some_collection:
# will it parallelise internal_tasklet execution?
m = yield internal_tasklet(data) # change here
models.appedn(m) # change here
keys = yield ndb.put_multi_async(models) # change here
raise ndb.Return(keys) # change here
編輯:
新修訂版…
@classmethod
@ndb.tasklet
def do_stuff(cls, some_collection):
@ndb.tasklet
def internal_tasklet(data):
do_some_long_taking_stuff(data)
id = make_stuff_needed_for_id(data)
model = yield cls.get_or_insert_async(id)
model.long_processing(data)
raise ndb.Return(model)
futures = []
for data in some_collection:
# tasklets won't run in parallel but while
# one is waiting on a yield (and RPC underneath)
# the other will advance it's execution
# up to a next yield or return
fut = internal_tasklet(data)) # change here
futures.append(fut) # change here
Future.wait_all(futures) # change here
models = [fut.get_result() for fut in futures]
keys = yield ndb.put_multi_async(models) # change here
raise ndb.Return(keys) # change here
如果你想做的只是用不同的 arguments 調用一些異步的東西,你不需要使用 tasklets - 只需返回包裝函數的返回值,就像這樣:
def get_or_insert_async(cls, *args):
id = cls.make_string_id(*args)
return super(MyModel, cls).get_or_insert_async(id)
不過,出於以下幾個原因,我對此持謹慎態度:您正在更改內置 function 的含義,這通常是個壞主意,您正在更改簽名(位置 arguments 但沒有關鍵字參數),並且您'沒有將額外的 arguments 傳遞給原來的 function。
對於你的第二個例子,一次產生一個東西將迫使 NDB 等待它們完成——'yield' 是 'wait' 的同義詞。 相反,為集合中的每個元素執行 tasklet function,然后同時等待它們(通過調用列表上的 yield)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.