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