我理解Python中的线程使用相同的Python解释器实例。我的问题与os.fork
创建的流程相同吗?或者os.fork
创建的每个进程都有自己的解释器吗?
答案 0 :(得分:14)
虽然fork
确实创建了当前Python解释器的副本而不是使用相同的Python解释器运行,但它通常不是您想要的,至少不是它自己的。其他问题包括:
fork
不正确。最臭名昭着的是,如果你让ssl
在主进程中播种它的PRNG,那么你现在有可能可预测的随机数,这是你安全的一个大漏洞。fork
和exec
之间实现一组非常具体的系统调用。如果您从未致电exec
,则只能使用这些系统调用。这基本上意味着你无法移植任何东西。fork
之后,任何与信号有关的内容都是,尤其是令人烦恼且无法移植。有关这些问题的详细信息,请参阅POSIX fork
或您平台的联机帮助页。
正确答案几乎总是使用multiprocessing
或concurrent.futures
(包装multiprocessing
)或类似的第三方库。
使用3.4+,您甚至可以指定start method。 fork
方法基本上只调用fork
。 forkserver
方法运行单个“干净”进程(没有线程,信号处理程序,SSL初始化等)并从中分离新的子进程。 spawn
方法会调用fork
,然后调用exec
,或类似posix_spawn
,以便为您提供全新的解释器,而不是副本。因此,您可以从fork
开始,如果有任何问题,请切换到forkserver
或spawn
,您的代码中的任何其他内容都不得更改。这很不错。
答案 1 :(得分:13)
每当你分叉时,整个Python进程都会在内存中重复(包括 Python解释器,你的代码和任何库,当前堆栈等)以创建第二个进程 - 这就是为什么分叉的一个原因进程比创建一个线程要贵得多。
这将创建python解释器的新副本。
运行两个python解释器的一个优点是你现在有两个GIL(全局解释器锁),因此可以在多核系统上进行真正的多处理。
一个进程中的线程共享相同的GIL,这意味着只有一个在给定时刻运行,只给出了并行性的错觉。
答案 2 :(得分:9)
os.fork()
相当于许多UNIC中的fork()
系统调用。所以是您的子流程将与父流分开并拥有不同的解释器(本身)。
FORK(2)
NAME fork - 创建子进程
概要 #include
pid_t fork(void);
说明 fork()通过复制调用进程来创建一个新进程。新过程,称为儿童, 是调用进程的完全重复,称为父进程,但以下几点除外:
os.fork()
分叉子进程。在孩子和...返回0 父级中的子进程ID。如果发生错误OSError是 提高。请注意,某些平台包括FreeBSD< = 6.3,Cygwin和OS / 2 EMX 从线程中使用fork()时会出现已知问题。
另见:Martin Konecny对于"分叉的原因和优势的回应" :)
为简洁起见;其他并发方法不涉及单独的进程,因此单独的Python解释器包括:
yield from