如何在不等待的情况下调用异步函数?

问题描述 投票:0回答:3

我在 aiohttp 应用程序中有一个控制器操作。

async def handler_message(request):

    try:
        content = await request.json()
        perform_message(x,y,z)
    except (RuntimeError):
        print("error in perform fb message")
    finally:
        return web.Response(text="Done")

perform_message
是异步函数。现在,当我调用 action 时,我希望我的 action 尽快返回并且
perform_message
放入事件循环。

这样,

perform_message
就没有被执行

python python-asyncio aiohttp
3个回答
74
投票

一种方法是使用

create_task
功能:

import asyncio

async def handler_message(request):
    ...
    loop = asyncio.get_event_loop()
    loop.create_task(perform_message(x,y,z))
    ...

根据 loop 文档,从 Python 3.10 开始,

asyncio.get_event_loop()
已弃用。如果你试图从协程/回调中获取循环实例,你应该使用
asyncio.get_running_loop()
代替。如果从主线程调用此方法将不起作用,在这种情况下必须实例化一个新循环:

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.create_task(perform_message(x, y, z))
loop.run_forever()

此外,如果调用在整个程序运行时只进行一次并且不需要实例化其他循环(不太可能),您可以使用:

asyncio.run(perform_message(x, y, z))

此函数创建一个事件循环并在协程结束后终止它,因此只能在上述场景中使用。


2
投票

最简单的形式:

import asyncio
from datetime import datetime

def _log(msg : str):
    print(f"{datetime.utcnow()} {msg}")

async def dummy(name, delay_sec):
    _log(f"{name} entering ...")
    await asyncio.sleep(delay_sec)
    _log(f"{name} done for the day!")

async def main():
    asyncio.create_task(dummy('dummy1', 5)) # last to finish
    asyncio.create_task(dummy('dummy2', 3)) # 2nd
    asyncio.create_task(dummy('dummy3', 1)) # First to finish

    _log(f"Yo I didn't wait for ya!")
    await asyncio.sleep(10)

asyncio.get_event_loop().run_until_complete(main())

输出:

2022-09-18 00:53:13.428285 Yo I didn't wait for ya!
2022-09-18 00:53:13.428285 dummy1 entering ...
2022-09-18 00:53:13.428285 dummy2 entering ...
2022-09-18 00:53:13.428285 dummy3 entering ...
2022-09-18 00:53:14.436801 dummy3 done for the day!
2022-09-18 00:53:16.437226 dummy2 done for the day!
2022-09-18 00:53:18.424755 dummy1 done for the day!

-3
投票

其他方法是使用

ensure_future
功能:

import asyncio

async def handler_message(request):
...
loop = asyncio.get_event_loop()
loop.ensure_future(perform_message(x,y,z))
...
© www.soinside.com 2019 - 2024. All rights reserved.