我从未使用过async-await
语法,但我经常需要在等待将来的响应时发出HTTP / S请求并解析响应。为了完成这个任务,我目前使用ThreadPoolExecutor类来反向执行异步调用;实际上,我实现了(我相信)与使用async-await
的更多代码行相同的结果。
在假设我当前的实现异步工作的情况下运行,我想知道async-await
实现与我使用Threads和Queue来管理worker的原始实现有什么不同;它还使用信号量来限制工人。
该实施是在以下条件下设计的:
实施的基本流程如下:
while
检查ListeningQueue因为我需要限制活动线程的数量,所以我使用信号量,如果我使用async-await
尝试这个,我必须在主线程或async def
中设计一些逻辑,以防止在限制时发送请求已达成。除了这个限制,我没有看到使用async-await
更有用的地方。是通过消除线程来降低开销和竞争条件的机会吗?这是主要的好处吗?如果是这样,即使使用ThreadPoolExecutor进行异步调用,它也使用了一个Threads池,从而使async-await
成为更好的选择?
在假设我当前的实现是异步工作的情况下运行,我想知道async-await实现将如何与我使用Threads和Queue来管理worker的原始实现不同
使用asyncio和async-await来实现非常相似的逻辑并不难,它有自己的semaphore版本,它的使用方式大致相同。有关使用固定数量的任务限制并行请求数或使用信号量的示例,请参阅this question的答案。
至于asyncio相对于使用线程的等效代码的优势,有几个:
await
标记,并且其间的所有内容都是有效的原子。这种优势在小型线程程序中不那么明显,其中执行程序只是以火灾和收集方式将任务交给线程,但随着逻辑变得越来越复杂并且线程开始共享更多状态(例如由于缓存或某些同步逻辑),这变得更加明显。await
等待某些事情发生(并将控制权交给其他人) - 例如基于计时器的监视任务将包含一个等待asyncio.sleep()
的循环,但逻辑可能是任意复杂的。尽管代码看起来是顺序的,但每个任务都是轻量级的,并且对操作系统的重要性不如小的分配对象。await
中醒来,但会终止它。取消可以直接实现超时,任务组和其他模式,这些模式在使用线程时是不可能的,也是一项繁重的工作。另一方面,async / await的缺点是所有代码都必须是异步的。除此之外,它意味着你不能使用像请求这样的库,你必须切换到像aiohttp这样的asyncio感知的替代品。