2015-05-11 17 views

risposta

12

Ogni volta che la forcella, l'intero processo di Python è duplicato in memoria (incluso l'interprete Python, il codice e le eventuali librerie, lo stack corrente ecc.) Per creare un secondo processo: uno dei motivi per cui la biforcazione di un processo è molto più costosa della creazione di un thread.

Questo crea una nuova copia dell'interprete python.

Un vantaggio di avere due interpreti Python in esecuzione è che ora avete due GIL (Global Interpreter Locks) e quindi possono avere una vera multielaborazione su un sistema multi-core.

I thread in un processo condividono lo stesso GIL, vale a dire solo una corsa in un dato momento, dando solo l'illusione del parallelismo.

9

os.fork() è equivalente al syscall fork() in molti UNIC (es). Quindi i tuoi processi secondari saranno separati dal genitore e avranno un interprete diverso (come tale).

man fork:

FORCELLA (2)

NOME fork - crea un processo figlio

SINOSSI #include

pid_t fork(void); 

DESCRIZIONE fork() crea un nuovo processo di dupli cating il processo di chiamata. Il nuovo processo, denominato come il bambino, è un duplicato esatto del processo chiamante, indicato come il genitore, fatta eccezione per i seguenti punti:

pydoc os.fork():

os.fork() Fork un bambino processi. Restituisce 0 nel figlio e l'id di processo del bambino nel genitore. Se si verifica un errore OSError è sollevato .

Si noti che alcune piattaforme tra cui FreeBSD < = 6.3, Cygwin e OS/2 EMX hanno problemi noti quando si utilizza fork() da un thread.

Consulta anche: la risposta di Martin Konecny ​​per quanto riguarda il perché e vantaggi del "forking" :)

Per brevità; altri approcci alla concorrenza che non implicano un processo separato e quindi un interprete Python separato includono:

+0

Una cosa da notare: 'asyncio' utilizza effettivamente coroutines yield (anche se in 3.5, può utilizzare le nuove coroutine [' async'/'await'] (https://www.python.org/dev/ peps/pep-0492 /) invece). Potrebbe anche essere utile menzionare disegni di callback/driven-driven più espliciti come Twisted, e semplicemente il looping diretto su un 'selector' o' select'. O gli equivalenti con loop di eventi in stile GUI. Ma ti ho già dato un +1, quindi potresti non ottenere alcun voto in più per aggiungere tutto questo.:) – abarnert

+0

@abarnert Ci andate :) È bello includere le varie opzioni Sono d'accordo :) –

14

Mentre fork effettivamente crea una copia dell'attuale interprete Python piuttosto che in esecuzione con la stessa, di solito non è ciò che si desidera, almeno non da solo. Tra gli altri problemi:

  • Ci possono essere problemi che biforcano processi multi-thread su alcune piattaforme. E alcune librerie (la più famosa Cocoa/CoreFoundation di Apple) possono avviare i thread per te in background, o usare le API locali del thread anche se hai solo un thread, ecc., A tua insaputa.
  • Alcune librerie presuppongono che ogni processo verrà inizializzato correttamente, ma se si fork dopo l'inizializzazione non è vero. La cosa più triste, se si lascia che ssl semini il suo PRNG nel processo principale, quindi fork, ora si hanno numeri casuali potenzialmente prevedibili, che è un grosso buco nella sicurezza.
  • I descrittori di file aperti vengono ereditati (come duplicati) dai bambini, con dettagli che variano in modi fastidiosi tra le piattaforme.
  • POSIX richiede solo piattaforme per implementare un insieme molto specifico di syscall tra uno fork e uno exec. Se non si chiama mai exec, è possibile utilizzare solo tali syscall. Il che significa sostanzialmente che non puoi fare il nulla di.
  • Tutto ciò che riguarda i segnali è in particolare fastidioso e non impostabile dopo fork.

Vedere POSIX fork o la pagina di manuale della piattaforma per i dettagli su questi problemi.

La risposta corretta è quasi sempre quella di utilizzare multiprocessing o concurrent.futures (che avvolge multiprocessing) o una libreria di terze parti simile.

Con 3.4+, è anche possibile specificare un start method. Il metodo fork fondamentalmente chiama solo fork. Il metodo forkserver esegue un singolo processo "pulito" (senza thread, gestori di segnale, inizializzazione SSL, ecc.) E allontana i nuovi bambini da quello. Il metodo spawn chiama fork quindi exec o un equivalente come posix_spawn, per ottenere un interprete nuovo di zecca anziché una copia. Quindi puoi iniziare con fork, quindi se ci sono dei problemi, passa a forkserver o spawn e nient'altro nel tuo codice deve cambiare. Che è molto carino

+1

Risposta piacevole ad alcuni dei molti avvertimenti di "blindly' 'fork()' 'ing" :) –

+0

@JamesMills: Ora che metti "ciechi" e "forchetta" insieme, ho gli Angry Samoans [Lights Out] (http://www.plyrics.com/lyrics/angrysamoans/lightsout.html) bloccati nella mia testa, e non è sul mio iTunes Match. Molte grazie. : P – abarnert

+0

Hahaha scusa! :) I giochi sono divertenti anche se si divertono a proprie spese :) –

Problemi correlati