如何同时执行多个协程并在某些协程完成时执行某些操作?
How to execute multiple coroutines concurrently and do something when some coroutines finishes?
上下文
我有三个食谱 类,它们共享一个共同的成分。
class BrewedNoodle:
ingredients: list[Coroutine] = [Noodle]
async def cook(noodle: Noodle):
pass
class PorkNoodle:
ingredients: list[Coroutine] = [Noodle, Pork]
async def cook(noodle: Noodle, pork: Pork):
pass
class BeefNoodle:
ingredients: list[Coroutine] = [Noodle, Beef]
async def cook(noodle: Noodle, beef: Beef):
pass
请将每个成分视为一个API(需要网络调用)
我想做什么
我想执行 asyncio.gather()
以同时获取(准备)每种成分。
一旦为特定食谱准备好所有必要的食材,我想立即烹饪,而不是等待其他食材。
例如:
- 面条一做好,我就煮BrewedNoodle。
- 猪肉准备好了,(因为面条和猪肉都准备好了)然后我煮猪肉面。
- 牛肉准备好后,我煮牛肉面。
我实际做了什么
但我在等待asyncio.gather()
,我注定要等到所有材料都准备好。 (即使面条做好了也无法预煮BrewedNoodle)
# prepare ingredients
noodle, pork, beef = await asyncio.gather(Noodle(), Pork(), Beef())
# cook
BrewedNoodle().cook(noodle)
PorkNoodle().cook(noodle, pork)
BeefNoodle().cook(noodle, beef)
问题
如何在必要的食材准备就绪的情况下不等待其他食材来烹饪食谱?
如果我对您的示例的理解正确,则需要某种从成分到可以从中创建的菜肴的明确映射。其他菜肴需要 Noodle
的特殊情况也需要单独解决。算法的核心是asyncio.as_completed()
:
dishes = {
Noodle: BrewedNoodle,
Pork: PorkNoodle,
Beef: BeefNoodle,
}
ingredients = [Noodle(), Pork(), Beef()]
noodle = None
for coro in asyncio.as_completed(ingredients):
ingredient = await coro
dish = dishes[type(ingredient)]
if isinstance(ingredient, Noodle):
dish.cook(ingredient)
noodle = ingredient
else:
# Pork or Beef, assuming noodle has already finished
dish.cook(noodle, ingredient)
上下文
我有三个食谱 类,它们共享一个共同的成分。
class BrewedNoodle:
ingredients: list[Coroutine] = [Noodle]
async def cook(noodle: Noodle):
pass
class PorkNoodle:
ingredients: list[Coroutine] = [Noodle, Pork]
async def cook(noodle: Noodle, pork: Pork):
pass
class BeefNoodle:
ingredients: list[Coroutine] = [Noodle, Beef]
async def cook(noodle: Noodle, beef: Beef):
pass
请将每个成分视为一个API(需要网络调用)
我想做什么
我想执行 asyncio.gather()
以同时获取(准备)每种成分。
一旦为特定食谱准备好所有必要的食材,我想立即烹饪,而不是等待其他食材。
例如:
- 面条一做好,我就煮BrewedNoodle。
- 猪肉准备好了,(因为面条和猪肉都准备好了)然后我煮猪肉面。
- 牛肉准备好后,我煮牛肉面。
我实际做了什么
但我在等待asyncio.gather()
,我注定要等到所有材料都准备好。 (即使面条做好了也无法预煮BrewedNoodle)
# prepare ingredients
noodle, pork, beef = await asyncio.gather(Noodle(), Pork(), Beef())
# cook
BrewedNoodle().cook(noodle)
PorkNoodle().cook(noodle, pork)
BeefNoodle().cook(noodle, beef)
问题
如何在必要的食材准备就绪的情况下不等待其他食材来烹饪食谱?
如果我对您的示例的理解正确,则需要某种从成分到可以从中创建的菜肴的明确映射。其他菜肴需要 Noodle
的特殊情况也需要单独解决。算法的核心是asyncio.as_completed()
:
dishes = {
Noodle: BrewedNoodle,
Pork: PorkNoodle,
Beef: BeefNoodle,
}
ingredients = [Noodle(), Pork(), Beef()]
noodle = None
for coro in asyncio.as_completed(ingredients):
ingredient = await coro
dish = dishes[type(ingredient)]
if isinstance(ingredient, Noodle):
dish.cook(ingredient)
noodle = ingredient
else:
# Pork or Beef, assuming noodle has already finished
dish.cook(noodle, ingredient)