acc*_*rub 16 python multithreading multiprocessing python-asyncio
作为使用并发的新手,我对何时使用不同的 Python 并发库感到困惑。据我了解,多处理、多线程和异步编程是并发的一部分,而多处理是称为并行的并发子集的一部分。
我在网上搜索了有关在 python 中处理并发的不同方法,我遇到了多处理库、concurrenct.futures 的 ProcessPoolExecutor() 和 ThreadPoolExecutor() 以及 asyncio。让我困惑的是这些库之间的区别。特别是 multiprocessing 库的作用,因为它有像 pool.apply_async 这样的方法,它是否也做 asyncio 的工作?如果是这样,当它是从 asyncio 实现并发性的不同方法(多进程与协作多任务)时,为什么将其称为多处理?
use*_*342 22
有几个不同的库在起作用:
threading: 操作系统级线程的接口。请注意,受 CPU 限制的工作主要由GIL序列化,因此不要指望您的计算会加速。当您需要并行调用阻塞 API 时使用它,特别是当您需要控制线程创建时。避免创建太多线程,因为它们很昂贵。
multiprocessing: 生成多个 python 进程的接口,其 API 有意类似于threading. 多个进程并行工作,因此您实际上可以使用此方法加快计算速度。缺点是您不能在不使用多处理特定工具的情况下共享内存中的数据结构。
concurrent.futures:一个更现代的界面threading和multiprocessing,它提供了方便的线程/进程池,它调用执行者。池的主要入口点是submit返回句柄的方法,您可以测试该句柄是否完成或等待其结果。获取结果将为您提供提交函数的返回值并正确传播引发的异常(如果有),这对于threading. 在考虑基于线程或进程的并行性时,concurrent.futures 应该是首选工具。
asyncio:虽然之前的选项在提供非阻塞API的意义上是“异步的” (这是apply_async和其他人所指的),但他们仍然依赖线程/进程池来发挥他们的魔力,并且不能真正做更多的事情平行于他们在池中的工人。Asyncio 全面使用单线程执行和异步系统调用。它根本没有阻塞调用,唯一的阻塞部分是asyncio.run()入口点。Asyncio 代码通常使用协程编写,协程使用await暂停直到有趣的事情发生。(挂起与阻塞不同,它允许事件循环线程在您等待时继续执行其他操作。)与基于线程的解决方案相比,它具有许多优点,例如能够产生数千个廉价的“任务”而无需使系统陷入困境,并且能够取消任务或轻松地同时等待多个事情。Asyncio 应该是服务器和连接到多个服务器的客户端的首选工具。
在 asyncio 和多线程/多处理之间进行选择时,请考虑“线程用于并行工作,而异步用于并行等待”的格言。
另请注意,asyncio 可以等待在由 提供的线程或进程池中执行的函数concurrent.futures,因此它可以作为所有这些不同模型之间的粘合剂。这是 asyncio 经常被用来构建新的库基础设施的部分原因。