Python: Call asynchronous code from synchronous method when there is already an event loop running(Python:当已经有一个事件循环正在运行时,从同步方法调用异步代码)
本文介绍了Python:当已经有一个事件循环正在运行时,从同步方法调用异步代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在和FastAPI和uvloop合作,高效地提供睡觉API服务。
我有很多异步代码调用远程资源,如数据库、存储等,这些函数如下所示:
async def _get_remote_resource(key: str) -> Resource:
# do some async work
return resource
我正在实现一个到现有抽象基类的接口,其中我需要在同步方法中使用上面的异步函数。我做了一些类似的事情:
class Resource:
def __str__(self):
resource = asyncio.run_until_complete(_get_remote_resource(self.key))
return f"{resource.pk}"
太好了!现在,我在FastAPI中执行一个端点,以使此工作可访问:
@app.get("")
async def get(key):
return str(Resource(key))
问题是FastAPI已经使用uvloop获取并运行事件循环,然后异步代码失败,因为循环已经在运行。
有没有什么方法可以从类中的同步方法调用异步方法?或者我必须重新考虑代码的结构?
推荐答案
运行时错误旨在阻止您尝试执行的操作。run_until_complete是阻塞调用,在异步def内使用它将停止外部事件循环。
最简单的解决方法是通过实际的异步方法公开所需的功能,例如:
class Resource:
def name(self):
return loop.run_until_complete(self.name_async())
async def name_async(self):
resource = await _get_remote_resource(self.key)
return f"{resource.pk}"
然后在FastAPI中,您将以原生方式访问API:
@app.get("")
async def get(key):
return await Resource(key).name_async()
您还可以将__str__(self)定义为返回self.name(),但最好避免这样做,因为像str()这样的基本内容也应该可以从Asyncio内部调用(由于用于日志记录、调试等)。
这篇关于Python:当已经有一个事件循环正在运行时,从同步方法调用异步代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
编程基础网
本文标题为:Python:当已经有一个事件循环正在运行时,从同步方法调用异步代码
基础教程推荐
猜你喜欢
- pyserial - 可以从线程 a 写入串行端口,是否阻塞从线程 b 读取? 2022-01-01
- 尝试制作WhatsApp机器人 2022-01-01
- 用 Python 编写 Fortran 无格式文件 2022-01-01
- numpy float:比算术运算中内置的慢 10 倍? 2022-01-01
- 将 x 轴刻度更改为自定义字符串 2022-01-01
- 与常规 dict 相比,Python manager.dict() 非常慢 2022-01-01
- 由Python将MP3转换为MIDI(类型错误:无法加载插件:mtg-Melodia:Melodia) 2022-01-01
- Discord.py 缺少必需的参数 2022-01-01
- 在 Celery 工作人员中捕获 Heroku SIGTERM 以优雅地关 2022-01-01
- 使用生成器和迭代器时 Python 多循环失败 2022-01-01
