在3之间有一个权衡 多进程的启动方法 :
fork 更快,因为它对父进程的整个虚拟内存进行了写时复制,包括初始化的Python解释器、加载的模块和内存中构造的对象。
但是fork并没有复制父进程的线程。因此,在父进程中由其他线程持有的锁(在内存中)被卡在子进程中,没有自己的线程来解锁它们,当代码试图获取其中任何一个锁时,就会造成死锁。另外,任何有分叉线程的本地库都会处于崩溃状态。
复制的 Python 模块和对象可能是有用的,也可能不必要地使每个分叉的子进程变得臃肿。
子进程也 "继承 "了操作系统资源,如开放的文件描述符和开放的网络端口。这些也会导致问题,但Python可以解决其中的一些问题。
So fork是快速、不安全的,而且可能是臃肿的。
然而这些安全问题 不至于引起麻烦 取决于子进程做什么。
卵子 starts a Python child process from scratch without the parent process's memory, file descriptors, threads, etc. Technically, 卵子 forks a duplicate of the current process, then the child immediately calls exec to replace itself with a fresh Python, then asks Python to load the target module and run the target callable.
So 卵子 is safe, compact, and slower 因为Python必须加载、初始化自己、读取文件、加载和初始化模块,等等。
However it 可能不会明显变慢 与子进程所做的工作相比。
forkserver 分叉出一个当前 Python 进程的副本,该副本可以缩减到大约一个新的 Python 进程。这就成为 "分叉服务器 "进程。然后每次启动一个子进程时,它都会要求分叉服务器分叉一个子进程并运行其目标可调用程序。
这些子进程开始时都很紧凑,没有卡锁。
forkserver更加复杂,而且没有很好的文档。
博扬-尼科利奇的博客文章
解释了更多关于forkserver和其秘密的
set_forkserver_preload()
方法来预加载一些模块。要警惕使用一个没有记录的方法,特别是在
bug fix in Python 3.7.0
.
So forkserver是快速、紧凑和安全的,但它更复杂,而且没有很好的文档。 .
[文件对这些都不是很好,所以我综合了多个来源的信息并做了一些推断。请对任何错误发表评论。]