RuntimeError su Windows che prova il multiprocessing di Python


123

Sto provando il mio primo vero programma python formale usando Threading e Multiprocessing su una macchina Windows. Tuttavia, non sono in grado di avviare i processi, con Python che fornisce il seguente messaggio. Il fatto è che non sto avviando i miei thread nel modulo principale . I thread vengono gestiti in un modulo separato all'interno di una classe.

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

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.

Il mio codice originale è piuttosto lungo, ma sono stato in grado di riprodurre l'errore in una versione ridotta del codice. È suddiviso in due file, il primo è il modulo principale e non fa altro che 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()

@doctorlove Lo eseguo come python testMain.py
NG Algo

1
Certo - hai bisogno di un if name == ' main ' vedi le risposte e i documenti
doctorlove

1
@NGAlgo Il tuo script mi ​​è stato molto utile durante il debug di un problema con pymongo e multiprocessing. Grazie!
Clay

Risposte:


175

Su Windows i sottoprocessi importeranno (cioè eseguiranno) il modulo principale all'avvio. È necessario inserire una if __name__ == '__main__':guardia nel modulo principale per evitare di creare sottoprocessi in modo ricorsivo.

Modificato testMain.py:

import parallelTestModule

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

3
(sbatte il palmo contro la fronte) Doh! Funziona!!!! Grazie mille! Mi mancava il fatto che è il modulo principale originale che viene reimportato! Per tutto questo tempo ho provato il controllo " name ==" subito prima di avviare i miei processi.
NG Algo

1
Non riesco a importare "parallelTestModule". Sto usando Python 2.7. Dovrebbe funzionare fuori dagli schemi?
Jonny

2
@ Jonny Il codice per parallelTestModule.py fa parte della domanda.
Janne Karila,

1
@DeshDeepSingh Lo snippet di codice non è un esempio autonomo; è una modifica del codice OP
Janne Karila

1
@DeshDeepSingh Quel modulo fa parte della domanda.
Janne Karila

25

Prova a inserire il tuo codice all'interno di una funzione principale in testMain.py

import parallelTestModule

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

Vedi i documenti :

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

che dicono

"Assicurati che il modulo principale possa essere importato in modo sicuro da un nuovo interprete Python senza causare effetti collaterali indesiderati (come l'avvio di un nuovo processo)."

... usando if __name__ == '__main__'


9

Sebbene le risposte precedenti siano corrette, c'è una piccola complicazione su cui sarebbe utile rimarcare.

Nel caso in cui il modulo principale importi un altro modulo in cui le variabili globali o le variabili membro della classe sono definite e inizializzate per (o utilizzando) alcuni nuovi oggetti, potrebbe essere necessario condizionare tale importazione allo stesso modo:

if __name__ ==  '__main__':
  import my_module

3

Come ha detto @Ofer, quando si utilizzano altre librerie o moduli, è necessario importarli tutti all'interno del file if __name__ == '__main__':

Quindi, nel mio caso, è finita così:

if __name__ == '__main__':       
    import librosa
    import os
    import pandas as pd
    run_my_program()

0

Nel mio caso si trattava di un semplice bug nel codice, utilizzando una variabile prima che fosse creata. Vale la pena verificarlo prima di provare le soluzioni di cui sopra. Perché ho ricevuto questo particolare messaggio di errore, il Signore lo sa.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.