如何在没有等待的情况下调用异步功能?

Pas*_*ino 5 python python-asyncio aiohttp

我在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")
Run Code Online (Sandbox Code Playgroud)

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

这样,不执行perform_message

use*_*555 13

最简单的形式:

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())
Run Code Online (Sandbox Code Playgroud)

输出:

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!
Run Code Online (Sandbox Code Playgroud)


fre*_*ish 11

一种方法是使用create_task函数:

import asyncio

async def handler_message(request):
    ...
    loop = asyncio.get_event_loop()
    loop.create_task(perform_message(x,y,z))
    ...
Run Code Online (Sandbox Code Playgroud)

  • 是的,但是直到等待才开始,对吧?如果你想创建它,启动它,做其他事情然后等待它怎么办(它可能会完成,如果没有,它会阻塞直到完成) (4认同)
  • @Jeppe 不,create_task 将尽快启动它。我鼓励您测试它(您根本不必等待结果)。 (3认同)
  • @ЯктенсТид OP希望在事件循环中运行任务,大概是安排它执行,而不是立即执行。我们几乎无法控制事件循环及其执行任务的时间。还要定义“立即”,因为在多任务环境中你几乎无法保证这样的事情。 (3认同)
  • @ HossamAl-Dokkani Dude,发表评论前如何检查?它确实启动了任务。您不必等待。期。 (2认同)
  • @freakish,但我不想永远运行这个,我需要我的函数终止并使用 HttpResponse 进行响应,并且我不想“等待”结果。 (2认同)
  • @HossamAl-Dokkani 听着,没有办法在未运行的循环上运行异步函数。你**必须**开始循环。你可以通过 `loop.run_until_complete(coro)` 或 `loop.run_forever()` 来完成。请参阅:https://docs.python.org/3/library/asyncio-eventloop.html#running-and-stopping-the-loop 在您的情况下,您似乎正在寻找第一个选项。 (2认同)
  • @ЯктенсТид你也无法控制线程。由操作系统决定何时运行您的代码。由于 GIL,事情变得更糟。Python 的事件循环在设计上是单线程的。它不会并行运行任务。然而,我们的目标是并发性,即等待当前函数退出应该是亚毫秒级的延迟,这通常根本不是问题。不,我们无法控制它。就像我们无法控制我们使用的 99% 的软件一样。如果你想完全控制,你必须自己重新实现一切。那将是一场噩梦。 (2认同)
  • 从 Python 3.7 开始,您可以只使用 [`asyncio.create_task`](https://docs.python.org/3/library/asyncio-task.html# asyncio.create_task)。 (2认同)