2011-11-23 15 views
15

Sto usando Python 2.7, ho un codice che assomiglia a questo:compiti di esecuzione in parallelo in pitone

task1() 
task2() 
task3() 
dependent1() 

task4() 
task5() 
task6() 
dependent2() 

dependent3() 

Le uniche dipendenze qui sono i seguenti: dependent1 deve attendere tasks1-3, dependent2 esigenze attendere le attività 4-6 e dipendente3 deve attendere le dipendenze1-2 ... Quanto segue dovrebbe essere corretto: eseguire prima tutte le 6 attività in parallelo, quindi le prime due dipendenti in parallelo .. quindi la dipendente finale

Preferisco avere quante più attività possibile in parallelo, ho cercato su google per alcuni moduli ma speravo di evitare le librerie esterne e non sono sicuro di come La tecnica ue-Thread può risolvere il mio problema (forse qualcuno può raccomandare una buona risorsa?)

+0

Si consiglia di utilizzare i metodi * Queue.task_done * e * Queue.join * della libreria standard per sincronizzare i thread. Nella parte inferiore della pagina nei documenti della coda, troverai un esempio su come aspettare che altri thread finiscano le loro attività: http://docs.python.org/library/queue.html#Queue.Queue.join –

+0

Se il codice diventa più complesso, vale la pena guardare le librerie esterne, perché ci sono già cose da fare con le attività in esecuzione in parallelo mentre si assicura che le dipendenze funzionino in ordine. –

+0

A causa della GIL, i thread verranno eseguiti solo uno alla volta in Python standard. Le versioni future di Pypy che utilizzano STM potrebbero aggirare questo problema. –

risposta

24

La classe integrata threading.Thread offre tutto ciò che serve: start per iniziare una nuova discussione e join per attendere la fine di una discussione.

import threading 

def task1(): 
    pass 
def task2(): 
    pass 
def task3(): 
    pass 
def task4(): 
    pass 
def task5(): 
    pass 
def task6(): 
    pass 

def dep1(): 
    t1 = threading.Thread(target=task1) 
    t2 = threading.Thread(target=task2) 
    t3 = threading.Thread(target=task3) 

    t1.start() 
    t2.start() 
    t3.start() 

    t1.join() 
    t2.join() 
    t3.join() 

def dep2(): 
    t4 = threading.Thread(target=task4) 
    t5 = threading.Thread(target=task5) 

    t4.start() 
    t5.start() 

    t4.join() 
    t5.join() 

def dep3(): 
    d1 = threading.Thread(target=dep1) 
    d2 = threading.Thread(target=dep2) 

    d1.start() 
    d2.start() 

    d1.join() 
    d2.join() 

d3 = threading.Thread(target=dep3) 
d3.start() 
d3.join() 

alternativa ad aderire è possibile utilizzare Queue.join per aspettare la fine discussioni.

+1

Questo è fantastico! ma il mio compito funziona restituendo i valori che uso nelle funzioni dep, come posso ottenere i valori restituiti da t1, t2, t3 ecc.? –

+2

Il primo hit in SO mi dà http://stackoverflow.com/questions/1886090/return-value-from-thread – gecco

+0

Cosa succede se voglio passare alcuni argomenti nella funzione? – Lavish

2

Vedere Gevent.

Esempio di utilizzo:

import gevent 
from gevent import socket 

def destination(jobs): 
    gevent.joinall(jobs, timeout=2) 
    print [job.value for job in jobs] 

def task1(): 
    return gevent.spawn(socket.gethostbyname, 'www.google.com') 

def task2(): 
    return gevent.spawn(socket.gethostbyname, 'www.example.com') 

def task3(): 
    return gevent.spawn(socket.gethostbyname, 'www.python.org') 

jobs = [] 
jobs.append(task1()) 
jobs.append(task2()) 
jobs.append(task3()) 
destination(jobs) 

Speranza, questo è quello che state cercando.

+2

Davvero? L'OP ha richiesto una soluzione di multithreading utilizzando una tecnica Queue/Thread e voleva evitare le librerie esterne. Ma tu gli indichi un nido di dipendenze esterne e ignori le soluzioni di base fornite dalla libreria standard. –

+2

Punto ben preso. – meson10

Problemi correlati