2012-03-29 13 views
6

Volevo implementare un semplice programma python utilizzando l'esecuzione parallela. È legato all'I/O, quindi ho pensato che i thread sarebbero appropriati (al contrario dei processi). Dopo aver letto la documentazione di Queue e fork, ho pensato che qualcosa del genere potesse funzionare.Informazioni su os.fork e Queue.Queue

q = Queue.Queue() 

if os.fork():   # child 
    while True: 
     print q.get() 
else:     # parent 
    [q.put(x) for x in range(10)] 

Tuttavia, la chiamata get() non restituisce mai. Ho pensato che sarebbe tornato una volta che l'altro thread eseguiva una chiamata put(). Utilizzando il modulo threading, le cose si comportano più come mi aspettavo:

q = Queue.Queue() 

def consume(q): 
    while True: 
     print q.get() 

worker = threading.Thread (target=consume, args=(q,)) 
worker.start() 

[q.put(x) for x in range(10)] 

io proprio non capisco il motivo per cui l'approccio forcella non fare la stessa cosa. Cosa mi manca?

risposta

7

La chiamata di sistema POSIX fork crea un nuovo processo , piuttosto che una nuova filo all'interno dello stesso spazio indirizzo: funzione

La forcella() si crea un nuovo processo. Il nuovo processo (bambino processo) può essere una copia esatta del processo chiamante (genitore processo) ad eccezione di quanto di seguito dettagliate: [...]

Così il Queue viene duplicato nel primo esempio, piuttosto che condiviso tra genitore e figlio.

È possibile utilizzare multiprocessing.Queue invece o semplicemente usare le discussioni come nel tuo secondo esempio :)

Tra l'altro, utilizzando list comprehensions solo per gli effetti collaterali isn't good practice per diversi motivi. Si consiglia di utilizzare un ciclo for invece:

for x in range(10): q.put(x) 
+1

+1 per aver menzionato "multiprocessing". –

0

Forcella crea un nuovo processo. I processi figlio e genitore non condividono la stessa coda: è per questo che gli elementi inseriti dal processo genitore non possono essere recuperati dal bambino.

1

Per condividere i dati tra processi non collegati, è possibile utilizzare pipe denominate. Attraverso la funzione os.open() .. http://docs.python.org/2/library/os.html#os.open. Puoi semplicemente nominare un pipe come named_pipe = 'my_pipe' e in un diverso programma python usare os.open (named_pipe,), dove la modalità è WRONLY e così via. Dopo di che farai un FIFO per scrivere nella pipe. Non dimenticare di chiudere la tubazione e rilevare le eccezioni.