- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我的任务是将 Flask 项目迁移到异步 Python 网络服务器。我正在寻找模式以尽量减少这里的工作量。在我看来,或多或少,不可能将同步网络服务器逐步移植到异步网络服务器中。这让我觉得我误解了异步。
假设我想使用 asyncio sql 库,并在 asyncio 网络服务器中使用它,我们可能必须将以下方法堆栈更改为异步:
if __name__=='__main__':
asyncio.get_event_loop().run_until_complete(main)
> async def main()
> async def subfunc()
> async def subsubfunc()
> async def decorator1()
> async def decorator2()
> async def webapi()
> async def decorator3()
> async def decorator4()
> async def servicemethod()
> async def servicemethod_impl()
....
> async def decorator5()
> async def decorator6()
> async def repositorylayer()
> async def sqllibrary()
> async def sqllibrary2()
> async def asyncio_socket.read()
^^ 因为我们要等待 asyncio_socket.read(),所以堆栈中的每个函数都需要更改 async def
函数声明以及 await
关于它的依赖性。这对重构有一些严重的后果:
result = oldtest()
assert result==expected
result = asyncio.get_event_loop().run_until_complete(oldtest())
assert result==expected
通常,任何调用异步函数的同步函数都需要重构 async-await —— 即异步具有传染性。任何调用异步的代码都必须感染异步,无论它是否关心异步。
因为这意味着全局重构,所以除了最小的项目外,将 web 服务从同步领域逐步移植到异步领域似乎并不实际。我见过将执行转移到同步/异步屏障处的线程的解决方案。然而,这似乎是: - 引入线程安全问题 - 删除异步的好处必须是通信和上下文切换 - 由于 GIL 而降低了执行吞吐量。
但是,原则上,应该可以从同步函数调用异步函数:
def syncfunc2():
result = asyncio.get_event_loop().run_until_complete(asyncfunc1())
return result
async def asyncfunc3():
result = await asyncfunc2()
return result
def syncfunc4():
result = asyncio.get_event_loop().run_until_complete(asyncfunc3())
return result
但是,由于不明确的原因,Python 不允许这样做并失败:
RuntimeError: This event loop is already running
我认为可以安全地实现可重入事件循环。我们过去常常在线程用完时为线程执行程序执行此操作——run_until_complete 的调用者可以驱动事件循环的执行直到它返回,之后执行返回到原始执行程序(这可以防止 no-more-executors-but -等待执行死锁)。这在 Python 中特别容易,因为 GIL 允许我们简单地保证 event_loop 是:
因此从队列中提取任务并执行它是安全的。因为如果你重新进入 run_until_complete Python 会报错,它禁止这个,也禁止增量引入 async。
所以:
相关:
最佳答案
你想做什么 is to use gevent 。它允许您同时提供多个响应,而无需线程或对同步代码进行重大修改。
如果你想使用基于 asyncio
的方法,你将不得不面对这样一个事实,即每个处理网络 I/O 的函数(比如每个 Controller 或数据库交互)should be 都被重写了成为异步
。这样做是为了帮助解决与并发相关的问题。这是始终确定功能可能突然屈服的地方的唯一方法。
关于python - *为什么* run_until_complete 不可重入。如何在没有线程的情况下逐步移植到异步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59738489/
我是一名优秀的程序员,十分优秀!