python os.fork 使用相同的 python 解释器吗?

Does python os.fork uses the same python interpreter?

我知道 Python 中的线程使用相同的 Python 解释器实例。我的问题是它与 os.fork 创建的进程相同吗?还是 os.fork 创建的每个进程都有自己的解释器?

os.fork() 等同于许多 UNIC 中的 fork() 系统调用。所以 是的 你的子流程将与父流程分开并有不同的解释器( 如此 )。

man fork:

FORK(2)

NAME fork - create a child process

SYNOPSIS #include

   pid_t fork(void);

DESCRIPTION fork() creates a new process by duplicating the calling process. The new process, referred to as the child, is an exact duplicate of the calling process, referred to as the parent, except for the following points:

pydoc os.fork():

os.fork() Fork a child process. Return 0 in the child and the child’s process id in the parent. If an error occurs OSError is raised.

Note that some platforms including FreeBSD <= 6.3, Cygwin and OS/2 EMX have known issues when using fork() from a thread.

另请参阅:Martin Konecny 对 "forking" 的原因和优势的回应 :)

为简洁起见;其他不涉及单独进程并因此需要单独的 Python 解释器的并发方法包括:

每当你 fork 时,整个 Python 进程都会在内存中复制(包括 Python 解释器、你的代码和任何库、当前堆栈等.) 创建第二个进程 - 分叉进程比创建线程昂贵得多的原因之一。

这会创建 python 解释器的新副本

拥有两个 python 解释器的一个优势 运行 是您现在拥有两个 GIL(全局解释器锁),因此可以在多核系统上进行真正的多处理。

一个进程中的线程共享同一个 GIL,这意味着在给定时刻只有一个线程运行,给人一种并行的错觉。

虽然 fork 确实创建了当前 Python 解释器的副本而不是 运行 相同的解释器,但它通常不是您想要的,至少不是它的自己的。除其他问题外:

  • 在某些平台上分叉多线程进程可能会出现问题。一些库(最著名的是 Apple 的 Cocoa/CoreFoundation)可能会在后台为您启动线程,或者即使您只有一个线程也使用线程本地 API,等等,而您并不知情。
  • 一些库假定每个进程都将正确初始化,但如果您在初始化后 fork 则不是这样。最臭名昭著的是,如果你让 ssl 在主进程中播种它的 PRNG,然后分叉,你现在就有了潜在的可预测随机数,这对你的安全来说是一个大漏洞。
  • 打开的文件描述符由子项继承(作为副本),平台之间的详细信息以令人讨厌的方式变化。
  • POSIX 只需要平台在 forkexec 之间实现一组非常具体的系统调用。如果你从不调用 exec,你只能使用那些系统调用。这基本上意味着你不能任何事情便携。
  • 任何与信号有关的事情 尤其是 fork 之后变得烦人且不可移植。

有关这些问题的详细信息,请参阅 POSIX fork 或您的平台的联机帮助页。

正确答案几乎总是使用 multiprocessing, or concurrent.futures(包含 multiprocessing)或类似的第三方库。

对于 3.4+,您甚至可以指定 start methodfork 方法基本上只是调用 forkforkserver 方法运行单个 "clean" 进程(没有线程、信号处理程序、SSL 初始化等)并从中分叉出新的子进程。 spawn 方法先调用 fork,然后调用 exec,或类似 posix_spawn 的等效方法,为您提供全新的解释器而不是副本。因此,您可以从 fork 开始,但如果有任何问题,请切换到 forkserverspawn,代码中的其他任何内容都不必更改。挺好看的