我知道python中的线程使用python解释器的实例。我的问题与os.fork
创建的过程相同吗?或os.fork
创建的每个过程都有其自己的解释器?
每当您分叉时,整个python进程都会在内存中重复(包括 python Instraper,您的代码和任何库,当前堆栈等)以创建一个第二个过程 - 分叉一个过程比创建线程要贵得多的原因。
这将创建python解释器的新副本。
让两个Python解释器运行的一个优点是您现在有两个Gil(全局解释器锁),因此可以在多核系统上具有真实的多处理。
一个过程中的线程共享相同的吉尔,这意味着只有一个在给定时刻运行,只给出了并行性的幻觉。
,而 fork
确实确实创建了当前python解释器的副本,而不是使用相同的副本,通常不是您想要的,至少不是单独的。除其他问题:
- 在某些平台上分配多线程流程可能会出现问题。一些图书馆(最著名的是苹果的可可/核心梦)可能在后台为您启动线程,或者即使您只有一个线程等,即使您只有一个线程等,也可以使用线程 - 本地API。
- 一些库假定每个过程都会正确初始化,但是如果您在初始化后
fork
,则不为。最臭名昭著的是,如果让ssl
在主要过程中播种其PRNG,那么叉子,您现在有可能可预测的随机数,这是您安全性的一个大漏洞。 - 开放的文件描述符是孩子继承(作为DUP)的,在平台之间以令人讨厌的方式有所不同。
- POSIX仅需要平台即可在
fork
和exec
之间实现非常特定的SYSCALL集。如果您从不致电exec
,则只能使用这些SYSCALL。这基本上意味着您无法履行任何事情 - 与信号有关的任何事情都是尤其是
fork
之后令人讨厌且不容易出现。
有关这些问题的详细信息,请参见POSIX fork
或您的平台的manpage。
正确的答案几乎总是使用multiprocessing
或concurrent.futures
(结束multiprocessing
)或类似的第三方库。
使用3.4 ,您甚至可以指定一个开始方法。fork
方法基本上只是调用fork
。forkserver
方法运行一个"清洁"过程(没有线程,信号处理程序,SSL初始化等),并从中叉出新孩子。spawn
方法调用fork
,然后调用exec
或等效的posix_spawn
,以使您获得全新的解释器而不是副本。因此,您可以从fork
,UT开始,然后如果有任何问题,请切换到forkserver
或spawn
,并且代码中没有其他更改。这非常好。
os.fork()
等于许多Unic(ES)中的fork()
Syscall。因此,是您的子过程(ES)将与父母分开,并具有不同的解释器(这样)。
man fork
:
叉(2)
名称 叉 - 创建子过程
摘要 #include
pid_t fork(void);
描述 fork()通过复制调用过程来创建一个新的过程。新过程,称为孩子, 是调用过程的确切重复,除了以下几点外:
:
pydoc os.fork()
:
os.fork()
叉一个子过程。在孩子和 父母的孩子的过程ID。如果发生错误,则Oserror是 提起。请注意,某些平台在内 从线程使用fork()时有已知问题。
另请参阅:Martin Konecny对"分叉"的原因和优势的回应:
简洁;其他不涉及单独过程的并发方法的方法,因此单独的Python解释器包括:
- 绿色或轻质线;ala greenlet
- Coroutines Ala Python发电机和新的Python 3
yield from
- 异步I/O Ala Asyncio,扭曲,电路等