Как совместить многопроцессорность и eventlet
У меня есть задача запустить 2 процесса, и внутри каждого процесса нужно запустить 2 потока, чтобы действительно работать. Ниже приведен исходный код, который я использовал для имитации моего варианта использования.
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()
Когда я запускаю этот скрипт на python, мой ожидаемый результат выглядит примерно так:
Начать субработник 1,1 Начать субработник 1,2 Начать субработник 2,1 Начать субработник 2,2 Конечный субработник 1,1 Конечный субработник 1,2 Конечный субработник 2,1 Конечный субработник 2,2
Но то, что я действительно получил, это:
Начать субработник 1,1 Traceback (последний вызов был последним): Файл "/Users/leehom/python_local/lib/python2.7/site-packages/eventlet/greenpool.py", строка 82, в _spawn_n_impl Начать субработник 1,2 func(*args, **kwargs) Файл "/Users/leehom/Desktop/home/work_dir/source/snips/Test_multiprocessing_and_eventlet.py", строка 27, в программе запуска Начать субработник 2,1 если не th.is_alive(): Файл "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/process.py", строка 155, в is_alive Начать субработник 2,2 assert self._parent_pid == os.getpid(), "может тестировать только дочерний процесс" AssertionError: может тестировать только дочерний процесс Начать субработник 1,1 Начать субработник 1,2 Начать субработник 2,1 Начать субработник 2,2 Конечный субработник 1,1 Конечный субработник 1,2 Конечный субработник 2,1 Конечный субработник 2,2 Конечный субработник 1,1 Конечный субработник 1,2 Конечный субработник 2,1 Конечный субработник 2,2 Процесс завершен с кодом выхода 0
Кажется, пусковая установка была вызвана дважды. Я не понимаю, почему это произошло.
Если я прокомментирую одну строку в моей основной функции
def main():
pool = eventlet.GreenPool(size=2)
pool.spawn_n(launcher, 1)
# pool.spawn_n(launcher, 2)
pool.waitall()
Результат правильный:
Начать субработник 1,1 Начать субработник 1,2 Конечный субработник 1,1 Конечный субработник 1,2
Кто-нибудь знает, как я могу это исправить и почему эта проблема возникает?
2 ответа
По состоянию на 2018-01 гг. Eventlet и многопроцессорная обработка не очень хорошо работают вместе. Лучший вариант - порождать рабочие процессы извне. Второй лучший вариант os.fork()
создавать рабочие процессы и только потом import eventlet
,
Подпишитесь на эту проблему, чтобы получать уведомления о разрешении многопроцессорной совместимости. https://github.com/eventlet/eventlet/issues/147
Основной модуль должен быть импортируемым для правильной работы нескольких процессов. Не вызывайте main() в глобальном пространстве, используйте его так:
if name == 'main': main()