我从未使用过async-await
语法,但我经常需要发出 HTTP/S 请求并解析响应,同时等待未来的响应。为了完成这项任务,我目前使用线程池执行器 https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor无论如何异步执行调用的类;有效地,我正在实现(我相信)与使用更多行代码得到的相同结果async-await
.
假设我当前的实现是异步工作的,我想知道如何async-await
实现将不同于我原来使用线程和队列来管理工作人员的实现;它还使用信号量来限制工人。
该实施是在以下条件下设计的:
- 可能有任意数量的请求
- 活动请求总数可能为 4
- 仅在收到响应时发送下一个请求
实施的基本流程如下:
- 生成请求的容器
- 创建监听队列
- 为每个请求创建一个线程并传递 URL、ListeningQueue 和 Semaphore
- 每个线程尝试获取信号量(限制为4个线程)
- 主线程继续
while
检查监听队列
- 当线程收到响应时,放入ListeningQueue并释放Semaphore
- 等待线程获取信号量(过程重复)
- 主线程处理响应,直到计数等于请求数
因为我需要限制活动线程的数量,所以我使用信号量,如果我要尝试使用async-await
我必须在主线程或主线程中设计一些逻辑async def
如果达到限制,则阻止发送请求。除了这个限制之外,我不知道在哪里使用async-await
会更有用。是不是通过消除线程来降低开销和竞争条件机会?这是主要的好处吗?如果是这样,即使使用 ThreadPoolExecutor 进行异步调用,它也会使用线程池,从而使得async-await
更好的选择?
假设我当前的实现是异步工作的,我想知道 async-await 实现与我原来使用线程和队列来管理工作人员的实现有何不同
使用以下方法实现非常相似的逻辑并不困难asyncio https://docs.python.org/3/library/asyncio.html和 async-await,它有自己的版本信号 https://docs.python.org/3/library/asyncio-sync.html#asyncio.Semaphore其使用方式大致相同。查看答案这个问题 https://stackoverflow.com/q/48483348/1600898例如,通过固定数量的任务或使用信号量来限制并行请求的数量。
至于 asyncio 相对于使用线程的等效代码的优点,有以下几个:
无论活动连接的数量如何,一切都在单个线程中运行。您的程序可以扩展到大量并发任务,而不会用不合理数量的线程淹没操作系统,或者下载甚至在开始之前就必须等待线程池中的空闲槽。
正如您所指出的,单线程执行不太容易受到竞争条件的影响,因为可以发生任务切换的点被清楚地标记为await
,并且中间的所有内容实际上都是原子的。这样做的优点在小型线程程序中不太明显,其中执行器只是以发射和收集的方式将任务交给线程,但随着逻辑变得更加复杂并且线程开始共享更多状态(例如,由于缓存或某些原因)同步逻辑),这变得更加明显。
async/await 允许您轻松创建额外的独立任务,例如监视、日志记录和清理。当使用线程时,这些线程不适合执行器模型并且需要额外的线程,总是带有表明线程被滥用的设计味道。使用 asyncio,每个任务都可以像在自己的线程中运行一样,并使用await
等待某件事发生(并将控制权交给其他人) - 例如基于计时器的监控任务将包含一个等待的循环asyncio.sleep() https://docs.python.org/3/library/asyncio-task.html#asyncio.sleep,但逻辑可以任意复杂。尽管代码看起来是连续的,但每个任务都是轻量级的,并且对操作系统的影响并不比分配的小对象更大。
async/await 支持可靠消除,线程从未这样做过,而且很可能永远不会这样做。这经常被忽视,但在 asyncio 中完全有可能cancel https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel一个正在运行的任务,这会导致它从await
有一个终止它的异常。取消使得实现超时、任务组和其他模式变得简单,而这些模式在使用线程时是不可能的或繁重的工作。
另一方面,async/await 的缺点是所有代码都必须是异步的。除此之外,这意味着您不能使用像 requests 这样的库,您必须切换到异步感知的替代方案,例如aiohttp https://aiohttp.readthedocs.io/en/stable/.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)