![](/img/trans.png)
[英]How to properly create and run concurrent tasks using python's asyncio module?
[英]How to run concurrent operations using asyncio in python?
我想在 asyncio 中运行“N”个并发操作。 这是我的代码的一般布局。
def heavy_operation():
# Heavy operation 1....N I want to run concurrently.
for x in range (N) :
heavy_operation()
heavy_operation
是我向 API 发出的GET
请求。 几行字符串一次。 由于 N 接近 100,我的代码运行缓慢。
只要繁重的操作同时运行,不使用 for 循环的解决方案也可以。
如果您的繁重操作不是异步的(使用async def
定义并实际等待 IO 操作),那么 asyncio 不会对您有多大好处,因为它是单线程的并且适合并行化 IO。 当并行化 CPU-bound 代码时,您可以直接使用线程,如下所示:
import concurrent.futures
with concurrent.futures.ThreadPoolExecutor() as pool:
for i in range(N):
pool.submit(heavy_operation) # you can also add positional arguments
请注意,如果heavy_operation
受 CPU 限制,由于GIL的原因,您的代码运行速度可能不会比顺序版本快。 在这种情况下,您可以尝试将ThreadPoolExecutor
更改为ProcessPoolExecutor
以在单独的 python 进程中运行heavy_operation
。
如果heavy_operation
是IO 绑定的(例如,它使用requests
下载http),最佳方法是通过将底层库切换到支持asyncio 的库来将其转换为异步,例如从requests
到aiohttp
。 然后,您将使用asyncio.gather
并行运行heavy_operation
,如此处和其他地方所示。
话虽如此,我还要补充一点,实际上,生成 100 个线程(假设您希望所有请求并行运行)不会妨碍现代系统。 您只需将该数字传递给ThreadPoolExecutor
构造函数,它就可以正常工作。 asyncio 的好处是您获得的解决方案:a) 实际可扩展,因为它同样适用于 10、100 或 10,000 个并发连接,b) 避免线程的许多陷阱,例如竞争条件,以及 c)自动提供其他好处,例如可靠的取消和超时。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.