Cómo combinar multiprocesamiento y eventlet
Tengo una tarea que necesita iniciar 2 procesos y dentro de cada proceso necesito iniciar 2 hilos para que realmente funcione. A continuación se muestra el código fuente que utilicé para simular mi caso de uso.
import multiprocessing
import eventlet
def subworker(num1, num2):
print 'Start subworker %d,%d\n' % (num1, num2)
eventlet.sleep(10)
print 'End subworker %d,%d\n' % (num1, num2)
def worker(**kwargs):
number = kwargs['number']
pool = eventlet.GreenPool(size=2)
pool.spawn_n(subworker, number, 1)
pool.spawn_n(subworker, number, 2)
pool.waitall()
def launcher(number):
kwargs = {'number': number}
th = multiprocessing.Process(target=worker, kwargs=kwargs)
th.start()
while True:
if not th.is_alive():
break
eventlet.sleep(0)
th.join()
def main():
pool = eventlet.GreenPool(size=2)
pool.spawn_n(launcher, 1)
pool.spawn_n(launcher, 2)
pool.waitall()
main()
Cuando ejecuto este script de Python, mi salida esperada es algo así como:
Start subworker 1,1 Start subworker 1,2 Start subworker 2,1 Start subworker 2,2 End subworker 1,1 End subworker 1,2 End subworker 2,1 End subworker 2,2
Pero lo que realmente obtuve es:
Start subworker 1,1 Traceback (most recent call last): File "/Users/leehom/python_local/lib/python2.7/site-packages/eventlet/greenpool.py", line 82, in _spawn_n_impl Start subworker 1,2 func(*args, **kwargs) File "/Users/leehom/Desktop/home/work_dir/source/snips/Test_multiprocessing_and_eventlet.py", line 27, in launcher Start subworker 2,1 if not th.is_alive(): File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/process.py", line 155, in is_alive Start subworker 2,2 assert self._parent_pid == os.getpid(), 'can only test a child process' AssertionError: can only test a child process Start subworker 1,1 Start subworker 1,2 Start subworker 2,1 Start subworker 2,2 End subworker 1,1 End subworker 1,2 End subworker 2,1 End subworker 2,2 End subworker 1,1 End subworker 1,2 End subworker 2,1 End subworker 2,2 Process finished with exit code 0
Parece lanzador fue llamado dos veces. No entiendo por qué sucede esto.
Si comento una línea en mi función principal
def main():
pool = eventlet.GreenPool(size=2)
pool.spawn_n(launcher, 1)
# pool.spawn_n(launcher, 2)
pool.waitall()
El resultado es correcto:
Start subworker 1,1 Start subworker 1,2 End subworker 1,1 End subworker 1,2
¿Alguien sabe cómo puedo solucionar esto y por qué ocurre este problema?