2013-08-13 8 views
40

Sto provando il mio primissimo programma Python formale usando Threading e Multiprocessing su una macchina Windows. Non riesco tuttavia ad avviare i processi, con python che fornisce il seguente messaggio. Il fatto è che non sto lanciando i miei thread nel modulo principale. I thread sono gestiti in un modulo separato all'interno di una classe.RuntimeError su Windows che tenta il multiprocessing di python

EDIT: A proposito, questo codice funziona bene su Ubuntu. Non proprio sulle finestre

RuntimeError: 
      Attempt to start a new process before the current process 
      has finished its bootstrapping phase. 
      This probably means that you are on Windows and you have 
      forgotten to use the proper idiom in the main module: 
       if __name__ == '__main__': 
        freeze_support() 
        ... 
      The "freeze_support()" line can be omitted if the program 
      is not going to be frozen to produce a Windows executable. 

mio codice originale è piuttosto lunga, ma sono stato in grado di riprodurre l'errore in una versione ridotta del codice. È diviso in due file, il primo è il modulo principale e fa ben poco altro da importare il modulo che gestisce processi/thread e chiama un metodo. Il secondo modulo è dove si trova la carne del codice.


testMain.py:

import parallelTestModule 

extractor = parallelTestModule.ParallelExtractor() 
extractor.runInParallel(numProcesses=2, numThreads=4) 

parallelTestModule.py:

import multiprocessing 
from multiprocessing import Process 
import threading 

class ThreadRunner(threading.Thread): 
    """ This class represents a single instance of a running thread""" 
    def __init__(self, name): 
     threading.Thread.__init__(self) 
     self.name = name 
    def run(self): 
     print self.name,'\n' 

class ProcessRunner: 
    """ This class represents a single instance of a running process """ 
    def runp(self, pid, numThreads): 
     mythreads = [] 
     for tid in range(numThreads): 
      name = "Proc-"+str(pid)+"-Thread-"+str(tid) 
      th = ThreadRunner(name) 
      mythreads.append(th) 
     for i in mythreads: 
      i.start() 
     for i in mythreads: 
      i.join() 

class ParallelExtractor:  
    def runInParallel(self, numProcesses, numThreads): 
     myprocs = [] 
     prunner = ProcessRunner() 
     for pid in range(numProcesses): 
      pr = Process(target=prunner.runp, args=(pid, numThreads)) 
      myprocs.append(pr) 
#  if __name__ == 'parallelTestModule': #This didnt work 
#  if __name__ == '__main__':    #This obviously doesnt work 
#  multiprocessing.freeze_support()  #added after seeing error to no avail 
     for i in myprocs: 
      i.start() 

     for i in myprocs: 
      i.join() 
+0

Come si esegue questo? – doctorlove

+0

@doctorlove Lo eseguo come python testMain.py –

+0

Certo - hai bisogno di un __name__ == '__main__' vedi le risposte e i documenti – doctorlove

risposta

62

In Windows i sottoprocessi importeranno (cioè eseguire) il modulo principale inizio. È necessario proteggere il codice principale come questo per evitare di creare sottoprocessi in modo ricorsivo:

import parallelTestModule 

if __name__ == '__main__':  
    extractor = parallelTestModule.ParallelExtractor() 
    extractor.runInParallel(numProcesses=2, numThreads=4) 
+1

(gli batte il palmo contro la fronte) Doh! Funziona!!!! Grazie mille! Mi mancava il fatto che è il modulo principale originale che viene re-importato! Per tutto questo tempo stavo provando il "__name__ ==" controllo proprio prima di dove ho lanciato i miei processi. –

+1

Non riesco a importare 'parallelTestModule'. Sto usando Python 2.7. Dovrebbe funzionare fuori dalla scatola? – Jonny

+1

@Jonny Il codice per parallelTestModule.py è parte della domanda. –

12

prova a mettere il codice all'interno di una funzione principale di testMain.py

import parallelTestModule 

if __name__ == '__main__': 
    extractor = parallelTestModule.ParallelExtractor() 
    extractor.runInParallel(numProcesses=2, numThreads=4) 

Vedere il docs:

"For an explanation of why (on Windows) the if __name__ == '__main__' 
part is necessary, see Programming guidelines." 

che dicono

"Assicurarsi che il modulo principale possa essere importato in sicurezza da un nuovo interprete Python senza causare effetti collaterali indesiderati (ad esempio l'avvio di un nuovo processo )."

... utilizzando if __name__ == '__main__'

1

Anche se le risposte precedenti sono corrette, c'è una piccola complicazione sarebbe utile rimarcare.

Nel caso in cui il modulo principale importa altro modulo in cui le variabili globali o variabili membro di classe sono definiti e inizializzati a (o utilizzando) alcuni nuovi oggetti, potrebbe essere necessario condizione che l'importazione nello stesso modo:

se nome == 'principale '': import my_module

Problemi correlati