从同步函数调用异步函数,而同步函数继续:Python

Shi*_*gga 8 asynchronous python-3.x python-asyncio

在阅读了许多文档AsyncIO和文章后,我仍然找不到答案:异步运行函数(不使用线程)并确保调用此异步函数的函数继续执行。

伪代码:

async def functionAsync(p):
    #...
    #perform intensive calculations
    #...
    print ("Async loop done")

def functionNormal():
    p = ""
    functionAsync(p)
    return ("Main loop ended")

 print ("Start Code")
 print functionNormal()
Run Code Online (Sandbox Code Playgroud)

预期输出:

Start code
Main loop ended
Async loop done
Run Code Online (Sandbox Code Playgroud)

搜索使用的示例loop.run_until_complete,但不会返回 的打印值,functionNormal()因为它本质上是阻塞的。

Tak*_*ine 18

asyncio.run()只需在同步函数内使用即可。

def syncfunc():
    async def asyncfunc():
        await some_async_work()
    asyncio.run(asyncfunc())

syncfunc()
Run Code Online (Sandbox Code Playgroud)

请注意,当另一个异步事件循环在同一线程中运行时,无法调用 asyncio.run() 。

  • 当另一个循环正在运行时怎么办? (5认同)

小智 12

也许有点晚了,但我遇到了类似的情况,我通过使用 run_in_executor 在 Flask 中解决了它:

def work(p):
    # intensive work being done in the background


def endpoint():
    p = ""
    loop = asyncio.get_event_loop()
    loop.run_in_executor(None, work, p)
Run Code Online (Sandbox Code Playgroud)

但我不确定这有多安全,因为循环没有关闭。


esh*_*lev 9

这是一个用于同步异步操作的辅助函数:

import asyncio
import time

async def sleep_return(s):
    time.sleep(s)
    return 420

def async_to_sync(awaitable):
    loop = asyncio.get_event_loop()
    return loop.run_until_complete(awaitable)

async_result = async_to_sync(sleep_return(.69))
print(f"Result from async call: { async_result }")

# Output:
# Result from async call: 420
Run Code Online (Sandbox Code Playgroud)

您可以内联大多数对 asyncio api 的调用以进一步简化它,但这更干净一点,恕我直言


Mik*_*mov 6

asyncio不能在不使用线程的情况下“在后台”运行任意代码。正如user4815162342 所指出的,asyncio您运行的是阻塞主线程并管理协程执行的事件循环。

如果您想使用asyncio并利用它,您应该将所有使用协程的函数重写为协程,直到主函数 - 程序的入口点。这个主协程通常传递给run_until_complete. 这篇小文章更详细地揭示了这个话题。


由于您对 Flask 感兴趣,请看一下Quart:它是一个 Web 框架,它试图在asyncio. 该项目存在的原因是纯 Flask 与asyncio. Quart 是为了兼容而编写的。

如果你想继续使用纯 Flask,但有异步的东西,看看gevent。通过猴子补丁它可以使您的代码异步。尽管此解决方案有其自身的问题(这就是asyncio创建的原因)。

  • `asyncio.ensure_future(my_coro(param1, param2))` 在具有正在运行的事件循环的同步函数(如回调)内工作。 (8认同)