【问题标题】:How to get the someone task's return immediately not until all task completed in [asyncio]?如何在 [asyncio] 中完成所有任务之前立即获得某人任务的返回?
【发布时间】:2019-11-24 01:56:59
【问题描述】:

如何在 [asyncio] 中的所有任务完成之前立即获得某人任务的返回?

import asyncio
import time

print(f"now: {time.strftime('%X')}")

async def test1():
    print(f"test1 started at {time.strftime('%X')}")
    await asyncio.sleep(5)
    with open('test.txt', 'w') as f:
        f.write('...')
    return 'end....'

async def test2(num):
    print(f"test2 started at {time.strftime('%X')}")
    return num * num

async def main(num):
    res = await asyncio.gather(test1(), test2(num))
    return res

def my(num):
    return asyncio.run(main(num))[1]

print(my(5))
print(f"all end at {time.strftime('%X')}")

从上面的代码(python 3.7+),我只能在test1test2都完成后才能得到test2return。

如何让main函数在test2完成后返回test2,而不是等到test1完成?,因为test2执行得更快。 并且必须执行 test1(生成 test.txt 文件。)

Than 表示 test1 和 test2 异步时尽快返回(test2 的返回)到main 函数或my 函数。

【问题讨论】:

  • 那么为什么要运行 test1 呢?
  • @quamrana test1 是一个异步函数。我只是想在这里简化一下,我已经编辑了问题。

标签: python asynchronous return python-asyncio


【解决方案1】:

要运行一组 awaitables/coroutines 直到任何 Future/Task 完成或被取消 - 您需要 asyncio.wait coroutine:

...
async def main(num):
    done, pending = await asyncio.wait([test1(), test2(num)], 
                                       return_when=asyncio.FIRST_COMPLETED)
    for coro in done:
        return await coro


def my(num):
    return asyncio.run(main(num))


print(my(5))
print(f"all end at {time.strftime('%X')}")

return_when表示该函数应该何时返回


输出:

now: 18:50:16
test1 started at 18:50:16
test2 started at 18:50:16
25
all end at 18:50:16

但是由于您需要完成所有协程 - 使用 asyncio.as_completed 方法或打印来自 done 集的结果,然后 - 从 pending 集等待并将 print(my(5)) 更改为 my(5)

...
async def main(num):
    done, pending = await asyncio.wait([test1(), test2(num)],
                                       return_when=asyncio.FIRST_COMPLETED)
    for coro in done:
        print(await coro)
    for coro in pending:
        await coro


def my(num):
    return asyncio.run(main(num))


my(5)
print(f"all end at {time.strftime('%X')}")

【讨论】:

  • 这个方法我试过了,但是asyncio.FIRST_COMPLETED的缺点是会取消剩下的协程。这不是我想要的。我已经编辑了这个问题。
  • @stackoverflow26,无需过于复杂:因为您需要完成所有协程 - 从done 集合打印结果,然后 - 从pending 集合等待
  • 我错误地确认了答案,我问题的最后一句,我需要返回(不仅仅是打印)test2 的返回main 函数或my 函数,如果我在done前面使用pending,比如for coro in pending: await coro for coro in done: return coro.result()done中的coro会在pending完成后等待coro,但是如果交换订单,RETURN键会结束主功能。那么,如何在test1完成之前将test2的return返回给main函数呢?
  • @stackoverflow26,11 小时后改变主意真的很阴险。现在我觉得我过早地投票赞成这个问题。
  • 是的,它可以很容易地用一个单独的线程解决。我只想知道我是否可以用异步解决它。另外,再次感谢您粗鲁地取消答案。你的回答解决了我的疑惑。
猜你喜欢
  • 1970-01-01
  • 2014-08-25
  • 1970-01-01
  • 1970-01-01
  • 2015-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多