简体   繁体   English

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

[英]Does python os.fork uses the same python interpreter?

I understand that threads in Python use the same instance of Python interpreter. 我知道Python中的线程使用相同的Python解释器实例。 My question is it the same with process created by os.fork ? 我的问题是os.fork创建的进程是os.fork吗? Or does each process created by os.fork has its own interpreter? 或者os.fork创建的每个进程都有自己的解释器吗?

Whenever you fork, the entire Python process is duplicated in memory ( including the Python interpreter, your code and any libraries, current stack etc.) to create a second process - one reason why forking a process is much more expensive than creating a thread. 每当你分叉时,整个Python进程都会在内存中复制( 包括 Python解释器,你的代码和任何库,当前堆栈等)以创建第二个进程 - 这就是为什么分支进程比创建一个线程要昂贵得多的原因之一。

This creates a new copy of the python interpreter. 这将创建python解释器的新副本

One advantage of having two python interpreters running is that you now have two GIL's (Global Interpreter Locks), and therefore can have true multi-processing on a multi-core system. 运行两个python解释器的一个优点是你现在有两个GIL(全局解释器锁),因此可以在多核系统上进行真正的多处理。

Threads in one process share the same GIL, meaning only one runs at a given moment, giving only the illusion of parallelism. 一个进程中的线程共享相同的GIL,这意味着只有一个在给定时刻运行,只给出并行性的错觉。

While fork does indeed create a copy of the current Python interpreter rather than running with the same one, it usually isn't what you want, at least not on its own. 虽然fork确实创建了当前Python解释器的副本而不是使用相同的Python解释器运行,但它通常不是您想要的,至少不是它自己的。 Among other problems: 其他问题包括:

  • There can be problems forking multi-threaded processes on some platforms. 在某些平台上可能存在问题多线程进程的问题。 And some libraries (most famously Apple's Cocoa/CoreFoundation) may start threads for you in the background, or use thread-local APIs even though you've only got one thread, etc., without your knowledge. 一些库(最着名的Apple的Cocoa / CoreFoundation)可能会在后台为您启动线程,或者使用线程本地API,即使您只有一个线程等,在您不知情的情况下。
  • Some libraries assume that every process will be initialized properly, but if you fork after initialization that isn't true. 有些库假设每个进程都会正确初始化,但是如果你在初始化之后进行fork则不正确。 Most infamously, if you let ssl seed its PRNG in the main process, then fork, you now have potentially predictable random numbers, which is a big hole in your security. 最臭名昭着的是,如果你让ssl在主要进程中播种它的PRNG,那么你现在有可能可预测的随机数,这是你安全的一个大漏洞。
  • Open file descriptors are inherited (as dups) by the children, with details that vary in annoying ways between platforms. 子文件继承了打开的文件描述符(作为重复项),平台之间的烦人方式的细节有所不同。
  • POSIX only requires platforms to implement a very specific set of syscalls between a fork and an exec . POSIX只需要平台在forkexec之间实现一组非常特定的系统调用。 If you never call exec , you can only use those syscalls. 如果你从不调用exec ,你只能使用那些系统调用。 Which basically means you can't do anything portably. 这基本上意味着你无法轻易做任何事情
  • Anything to do with signals is especially annoying and nonportable after fork . 任何与信号有关的事情都特别令人讨厌并且在fork之后不可移植。

See POSIX fork or your platform's manpage for details on these issues. 有关这些问题的详细信息,请参阅POSIX fork或平台的联机帮助页。

The right answer is almost always to use multiprocessing , or concurrent.futures (which wraps up multiprocessing ), or a similar third-party library. 正确的答案几乎总是使用multiprocessingconcurrent.futures (包装multiprocessing )或类似的第三方库。

With 3.4+, you can even specify a start method . 使用3.4+,您甚至可以指定启动方法 The fork method basically just calls fork . fork方法基本上只调用fork The forkserver method runs a single "clean" process (no threads, signal handlers, SSL initialization, etc.) and forks off new children from that. forkserver方法运行一个“干净”的进程(没有线程,信号处理程序,SSL初始化等)并从中分叉新的子进程。 The spawn method calls fork then exec , or an equivalent like posix_spawn , to get you a brand-new interpreter instead of a copy. spawn方法调用fork然后exec ,或类似posix_spawn ,以获得一个全新的解释器而不是副本。 So you can start off with fork , ut then if there are any problems, switch to forkserver or spawn and nothing else in your code has to change. 所以你可以从fork开始,然后如果有任何问题,切换到forkserverspawn ,你的代码中没有别的东西必须改变。 Which is pretty nice. 这很不错。

os.fork() is equivalent to the fork() syscall in many UNIC(es). os.fork()等同于许多UNIC中的fork()系统调用。 So yes your sub-process(es) will be separate from the parent and have a different interpreter ( as such ). 所以是的,您的子流程将与父流分开并具有不同的解释器( 如此 )。

man fork : man fork

FORK(2) FORK(2)

NAME fork - create a child process NAME fork - 创建子进程

SYNOPSIS #include 大纲#include

  pid_t fork(void); 

DESCRIPTION fork() creates a new process by duplicating the calling process. 说明fork()通过复制调用进程来创建新进程。 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() : pydoc os.fork()

os.fork() Fork a child process. os.fork() fork一个子进程。 Return 0 in the child and the child's process id in the parent. 在子级中返回0,在父级中返回子级的进程ID。 If an error occurs OSError is raised. 如果发生错误,则引发OSError。

Note that some platforms including FreeBSD <= 6.3, Cygwin and OS/2 EMX have known issues when using fork() from a thread. 请注意,从线程使用fork()时,某些平台(包括FreeBSD <= 6.3,Cygwin和OS / 2 EMX)都存在已知问题。

See also: Martin Konecny's response as to the why's and advantages of "forking" :) 另请参阅:Martin Konecny对“分叉”的原因和优势的回应:)

For brevity; 为简洁起见; other approaches to concurrency which don't involve a separate process and therefore a separate Python interpreter include: 其他并发方法不涉及单独的进程,因此单独的Python解释器包括:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM