Como combinar multiprocessamento e eventlet
Eu tenho uma tarefa que precisa iniciar 2 processos e dentro de cada processo é necessário iniciar 2 threads para realmente funcionar. Abaixo está o código fonte que usei para simular meu 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()
Quando executo esse script python, minha saída esperada é algo 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
Mas o que realmente consegui é:
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 lançador foi chamado duas vezes. Eu não entendo por que isso acontece.
Se eu comentar uma linha na minha função principal
def main():
pool = eventlet.GreenPool(size=2)
pool.spawn_n(launcher, 1)
# pool.spawn_n(launcher, 2)
pool.waitall()
O resultado está certo:
Start subworker 1,1 Start subworker 1,2 End subworker 1,1 End subworker 1,2
Alguém sabe como posso resolver isso e por que esse problema acontece?