2015-04-27 12 views
5

Sto leggendo il tema Multiprocessing per Python 3 e cercando di integrare il metodo nel mio script, tuttavia ricevo il seguente errore:Come eseguire il multiprocessing per una singola funzione in Python?

AttributeError: __ exit __

Io uso Windows 7 con un I-7 processori 8-core, I avere uno shapefile di grandi dimensioni che desidero elaborare (con il software di mappatura, QGIS) utilizzando preferibilmente tutti gli 8 core. Di seguito è riportato il codice che ho, Io apprezzo molto di aiuto con questa materia:

from multiprocessing import Process, Pool 

def f(): 
    general.runalg("qgis:dissolve", Input, False, 'LAYER_ID', Output) 

if __name__ == '__main__': 
    with Pool(processes=8) as pool: 
     result = pool.apply_async(f) 
+1

La prima cosa che vorrei fare è sostituire il contenuto di f() con, ad esempio print, per restringere il problema. Se ciò dovesse accadere, c'è qualcosa di sbagliato nel tuo generale.runalg –

+0

@TymoteuszPaul - Grazie, ci proverò. Il 'general.runal' funziona bene da solo, quindi la mia ipotesi è qualcosa a che fare con il metodo' Pool'. – Joseph

+0

Inoltre hai accennato al fatto che stai scrivendo questo per python3, eppure stai usando la stampa in modo 2.7 che genera un errore. E potrebbe essere la causa di tutte le cose;) –

risposta

3

La caratteristica contesto manager della multiprocessing.Pool è stato aggiunto solo in Python 3.3:

New in version 3.3: Pool objects now support the context management protocol – see Context Manager Types. __enter__() returns the pool object, and __exit__() calls terminate() .

Il fatto che __exit__ non è definito suggerisce che stai usando la versione 3.2 o precedente. Avrete bisogno di chiamare manualmente terminate sul Pool per ottenere un comportamento equivalente:

if __name__ == '__main__': 
    pool = Pool(processes=8) 
    try: 
     result = pool.apply_async(f) 
    finally: 
     pool.terminate() 

Detto questo, probabilmente non si desidera utilizzare terminate (o la dichiarazione with, per estensione) qui. Il metodo __exit__ delle chiamate Pool chiama terminate, che interromperà forzatamente i dipendenti, anche se non hanno terminato il proprio lavoro. Probabilmente si vuole aspettare in realtà per il lavoratore di finire prima di uscire, il che significa che si dovrebbe chiamare close() invece, e quindi utilizzare join aspettare che tutti i lavoratori per finire prima di uscire:

if __name__ == '__main__': 
    pool = Pool(processes=8) 
    result = pool.apply_async(f) 
    pool.close() 
    pool.join() 
+0

Brillante, molte grazie per questo! Riesco a vedere gli 8 processi separati che si verificano nel Task Manager. La funzione non funziona correttamente, ma penso che sia nella mia parte, quindi giocherò con la sceneggiatura. Grazie ancora! – Joseph