在我的代码中,我有一个带有属性的类,它偶尔需要运行异步代码。有时我需要从异步函数访问属性,有时从同步函数访问属性——这就是为什么我不希望我的属性是异步的。此外,我的印象是异步属性通常是一种代码味道。如我错了请纠正我。
我在从同步属性执行异步方法并阻止进一步执行直到异步方法完成时遇到问题。
这是一个示例代码:
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()
函数最后执行,同步完成后。我想通过异步方法对数据集做一些处理,所以我需要等待它完成。 If I’ll add await asyncio.sleep(0)
after calling synchronous_property()
, it will call asynchronous()
before main()
finish, but it doesn’t help me.我需要运行 asynchronous()
之前 synchronous_property()
完成。
我错过了什么?我正在运行 python 3.7。
原文由 Andrzej Klajnert 发布,翻译遵循 CC BY-SA 4.0 许可协议
Asyncio 在 设计 上确实坚持不允许嵌套循环。但是,您始终可以在不同的线程中运行另一个事件循环。这是一个使用线程池的变体,以避免每次都必须创建一个新线程:
此代码在每个 sync->async 边界上创建一个新的事件循环,所以如果你经常这样做,不要期望高性能。可以通过使用
asyncio.new_event_loop
每个线程只创建一个事件循环并将其缓存在线程局部变量中来改进它。