Capisco che i thread in Python usano la stessa istanza dell'interprete Python. La mia domanda è la stessa con il processo creato da os.fork
? O ogni processo creato da os.fork
ha il proprio interprete?python os.fork utilizza lo stesso interprete python?
risposta
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.
os.fork()
è equivalente al syscall fork()
in molti UNIC (es). Quindi sì i tuoi processi secondari saranno separati dal genitore e avranno un interprete diverso (come tale).
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:
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:
- Filettature verdi o leggere; ala greenlet
- coroutine ala Python generatori e il nuovo Python 3+
yield from
- asincrone di I/O ala asyncio, Twisted, circuits, ecc
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 chessl
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 unoexec
. Se non si chiama maiexec
, è 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
Risposta piacevole ad alcuni dei molti avvertimenti di "blindly' 'fork()' 'ing" :) –
@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
Hahaha scusa! :) I giochi sono divertenti anche se si divertono a proprie spese :) –
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
@abarnert Ci andate :) È bello includere le varie opzioni Sono d'accordo :) –