Nel mio progetto sto usando la libreria Python multiprocessing
per creare più processi in __main__. Il progetto viene impacchettato in un unico file EXE di Windows utilizzando PyInstaller 2.1.1.L'EXE di Windows generato da PyInstaller non funziona con il multiprocessing
io creo nuovi processi in questo modo:
from multiprocessing import Process
from Queue import Empty
def _start():
while True:
try:
command = queue.get_nowait()
# ... and some more code to actually interpret commands
except Empty:
time.sleep(0.015)
def start():
process = Process(target=_start, args=args)
process.start()
return process
E in __main__:
if __name__ == '__main__':
freeze_support()
start()
Purtroppo, quando il confezionamento l'applicazione in un file EXE e il lancio, ottengo WindowsError
5 o 6 (sembra casuale) a questa riga:
command = queue.get_nowait()
Una ricetta alla homepage di PyInstaller afferma che Devo modificare il mio codice per abilitare la multielaborazione in Windows quando impacchetta l'applicazione come un singolo file.
sto riproducendo il codice qui:
import multiprocessing.forking
import os
import sys
class _Popen(multiprocessing.forking.Popen):
def __init__(self, *args, **kw):
if hasattr(sys, 'frozen'):
# We have to set original _MEIPASS2 value from sys._MEIPASS
# to get --onefile mode working.
# Last character is stripped in C-loader. We have to add
# '/' or '\\' at the end.
os.putenv('_MEIPASS2', sys._MEIPASS + os.sep)
try:
super(_Popen, self).__init__(*args, **kw)
finally:
if hasattr(sys, 'frozen'):
# On some platforms (e.g. AIX) 'os.unsetenv()' is not
# available. In those cases we cannot delete the variable
# but only set it to the empty string. The bootloader
# can handle this case.
if hasattr(os, 'unsetenv'):
os.unsetenv('_MEIPASS2')
else:
os.putenv('_MEIPASS2', '')
class Process(multiprocessing.Process):
_Popen = _Popen
class SendeventProcess(Process):
def __init__(self, resultQueue):
self.resultQueue = resultQueue
multiprocessing.Process.__init__(self)
self.start()
def run(self):
print 'SendeventProcess'
self.resultQueue.put((1, 2))
print 'SendeventProcess'
if __name__ == '__main__':
# On Windows calling this function is necessary.
if sys.platform.startswith('win'):
multiprocessing.freeze_support()
print 'main'
resultQueue = multiprocessing.Queue()
SendeventProcess(resultQueue)
print 'main'
La mia frustrazione con questa "soluzione" è che, uno, è assolutamente chiaro che cosa esattamente si patch, e, due, che è scritto in un tale modo complicato che diventa impossibile dedurre quali parti sono la soluzione e che sono solo un'illustrazione.
Qualcuno può condividere un po 'di luce su questo problema e fornire informazioni su cosa esattamente deve essere modificato in un progetto che consente la multiprocessing in file eseguibili di Windows a file singolo creati con PyInstaller?
Does la ricetta risolto il problema? – dano
Beh, non è chiaro (almeno per me) come applicare la ricetta. Anche incollare il codice precedente nel mio script Python principale non funziona, poiché solleva altre due eccezioni non correlate ai miei script Python. Il che mi dice che la ricetta è fondamentalmente difettosa. – nikola
Se si esegue la ricetta solo come script autonomo, viene eseguita senza errori? – dano