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

时间:2019-04-12 08:45:58

标签: python-3.x asynchronous python-asyncio

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

伪代码-

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

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

 print ("Start Code")
 print functionNormal()

预期输出:

Start code
Main loop ended
Async loop done

搜索了使用loop.run_until_complete的示例,但由于它实际上是阻塞的,因此不会返回functionNormal()的打印值。

3 个答案:

答案 0 :(得分:0)

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

如果要使用asyncio并加以利用,则应重写所有使用协程的函数,直到主函数-程序入口点为止都是协程。该主要协程通常传递给run_until_completelittle post更加详细地揭示了这一主题。


由于您对Flask感兴趣,因此请看一下Quart:这是一个Web框架,它试图以asyncio的形式来实现Flask API(尽可能多地)。该项目存在的原因是因为纯Flask与asyncio不兼容。 Quart被编写为兼容。

如果您希望使用纯Flask,但又需要异步处理,请查看gevent。通过猴子补丁,它可以使您的代码异步。尽管此解决方案有其自身的问题(创建asyncio的原因)。

答案 1 :(得分:0)

也许有点晚了,但是我遇到了类似的情况,我通过使用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)

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

答案 2 :(得分:0)

假设同步函数位于异步函数内部,则可以使用异常来解决它。 伪代码:

class CustomError(Exception):
pass


async def main():
    def test_syn():
        time.sleep(2)
        # Start Async
        raise CustomError
    try:
        test_syn()
    except CustomError:
        await asyncio.sleep(2)