等待一切完成(异步)

时间:2019-06-18 12:52:03

标签: python python-asyncio

我正在玩asyncio,但无法实现我想要达到的目标。这是我的代码。

import random
import asyncio

async def my_long_operation(s: str):
    print("Starting operation on", s)
    await asyncio.sleep(3)
    print("End", s)


def random_string(length: int = 10):
    alphabet = \
            [chr(x) for x in range(ord('a'), ord('z') + 1)]

    result = ""
    for i in range(length):
        result += random.choice(alphabet)
    return result


def get_strings(n = 10):
    for i in range(n):
        s = random_string()
        yield s

async def several(loop):
    tasks =list()
    for s in get_strings():
        task = asyncio.create_task(my_long_operation(s))
        asyncio.ensure_future(task, loop = loop)

    print("OK")

loop = asyncio.get_event_loop()
loop.run_until_complete(several(loop))
# loop.run_forever()
loop.close()

现在我的问题如下。 我想同时运行所有my_long_operation,以等待它们完成。问题是,当我运行代码时,出现以下错误:

Task was destroyed but it is pending!
task: <Task pending coro=<my_long_operation() done, defined at test.py:4> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f75274f7168>()]>>

这似乎很有意义,因为我的脚本在启动这些操作后即刻结束(无需等待它们完成)。

因此,我们得出了我的实际问题:我应该怎么做?如何在不使用run_forever的情况下启动这些任务并等待它们完成,然后再终止脚本,而无需使用run_forever(因为fun getAllDynamicUtterances(): LiveData<ArrayList<DynamicUtterance>> { var uttList: ArrayList<DynamicUtterance>? = null disposable?.add( repository.getDynamicScreenContent().map { items -> items.uttSets.map { //items = DynamicUtterance var utt: DynamicUtterance? = null utt?.makeUtteranceFromScreenContentResponse(it) insertDynamicUtterance(utt!!) repository.updateDynamicUtteranceView(utt,"hi").map{ //it: SelectionStringResponse utt.assignSelectionStrings(it) uttList?.add(utt) //how do i add to all dynamic values? } } }.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()).subscribe ({ allDynamicUtterances?.value = uttList },{ Log.e("errorHandle",it.toString()) //gets caught here }) ) return allDynamicUtterances!! } 从不退出Python ...)

谢谢!

1 个答案:

答案 0 :(得分:3)

ensure_future基本上是“将其放入事件循环中,然后再打扰我”的方法。相反,您要等待所有异步功能的完成。为此,如果对结果不特别感兴趣,请使用asyncio.wait;如果需要结果,请使用asyncio.gather

tasks = map(my_long_operation, get_strings())
await asyncio.wait(list(tasks), loop=loop)
print('OK')