使用Python Asyncio运行并等待来自同步函数的异步函数 [英] Run and wait for asynchronous function from a synchronous one using Python asyncio

查看:25
本文介绍了使用Python Asyncio运行并等待来自同步函数的异步函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的代码中,我有一个带有属性的类,偶尔需要运行异步代码。有时我需要从异步函数访问属性,有时需要从同步函数访问属性-这就是为什么我不希望我的属性是异步的。此外,我有一种印象,异步属性通常是一种代码气味。如果我错了,请纠正我。

我在从Synchronous属性执行异步方法并在异步方法完成之前阻止进一步执行时遇到了问题。

以下是示例代码:

import asyncio


async def main():
    print('entering main')
    synchronous_property()
    print('exiting main')


def synchronous_property():
    print('entering synchronous_property')
    loop = asyncio.get_event_loop()
    try:
        # this will raise an exception, so I catch it and ignore
        loop.run_until_complete(asynchronous())
    except RuntimeError:
        pass
    print('exiting synchronous_property')


async def asynchronous():
    print('entering asynchronous')
    print('exiting asynchronous')


asyncio.run(main())

其输出:

entering main
entering synchronous_property
exiting synchronous_property
exiting main
entering asynchronous
exiting asynchronous
首先,RuntimeError捕获似乎是错误的,但是如果我不这样做,我会得到RuntimeError: This event loop is already running异常。

其次,asynchronous()函数在同步一完成后最后执行。我想通过异步方法对数据集进行一些处理,所以我需要等待它完成。 如果我在调用synchronous_property()之后添加await asyncio.sleep(0),它会在main()完成之前调用asynchronous(),但它对我没有帮助。我需要在synchronous_property()完成之前运行asynchronous()

我错过了什么?我正在运行python 3.7。

推荐答案

Asyncio确实坚持不允许嵌套循环,by design。但是,您始终可以在不同的线程中运行另一个事件循环。下面是一个变体,它使用线程池来避免每次都必须创建一个新线程:

import asyncio, concurrent.futures

async def main():
    print('entering main')
    synchronous_property()
    print('exiting main')

pool = concurrent.futures.ThreadPoolExecutor()

def synchronous_property():
    print('entering synchronous_property')
    result = pool.submit(asyncio.run, asynchronous()).result()
    print('exiting synchronous_property', result)

async def asynchronous():
    print('entering asynchronous')
    await asyncio.sleep(1)
    print('exiting asynchronous')
    return 42

asyncio.run(main())
这段代码在每个sync->异步边界上创建一个新的事件循环,所以如果您经常这样做,就不要期望高性能。通过使用asyncio.new_event_loop为每个线程仅创建一个事件循环,并将其缓存在线程局部变量中,可以对其进行改进。

这篇关于使用Python Asyncio运行并等待来自同步函数的异步函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆