Совместное использование gevent и multiprocessing для взаимодействия с подпроцессом - PullRequest
5 голосов
/ 12 февраля 2011

Вопрос:

Могу ли я эффективно использовать многопроцессорный модуль вместе с Gevent в Windows?

Сценарий:

У меня есть приложение Python на основе Gevent, которое выполняет асинхронный ввод-вывод в Windows. Приложение в основном связано с вводом / выводом, но также наблюдаются скачки загрузки процессора. Это приложение должно управлять консольным приложением через его стандартный ввод и стандартный вывод. Я не могу изменить это консольное приложение, и пользователь сможет использовать свое собственное, только фиксированный протокол связи на основе текста (строки).

У меня есть рабочая реализация, использующая подпроцесс и потоки, но я бы предпочел перенести весь код связи на основе подпроцесса вместе с этими потоками в отдельный процесс, чтобы превратить основное приложение в однопоточное. Я планирую использовать для этого многопроцессорный модуль.

До прочтения:

Я много искал в Интернете и читал некоторый исходный код, поэтому я знаю, что многопроцессорный модуль использует реализацию Pipe, основанную на именованных каналах в Windows. Пара объектов multiprocessing.queue.Queue будет использоваться для связи со вторым процессом Python. Эти очереди основаны на той реализации Pipe, например, IPC будет осуществляться через именованные каналы.

Ключевой вопрос заключается в том, блокирует ли вызов метода get входящей очереди основной цикл gevent или нет. У этого метода есть тайм-аут, поэтому я мог бы превратить его в цикл с небольшим тайм-аутом, но это не очень хорошее решение, так как он все еще блокировал бы gevent на небольшие промежутки времени, нанося ущерб его низкой задержке ввода / вывода.

Я также открыт для предложений о том, как обойти всю проблему использования каналов в Windows, которая, как известно, является сложной, а иногда и хрупкой. Я не уверен, возможен ли IPC на основе общей памяти в Windows или нет. Возможно, я мог бы обернуть консольное приложение таким образом, чтобы можно было обмениваться данными с дочерним процессом с помощью сетевых сокетов, что, как известно, хорошо работает с gevent.

Пожалуйста, не ставьте под сомнение мой основной вариант использования, если это возможно. Спасибо.

Ответы [ 2 ]

1 голос
/ 24 февраля 2011

Метод get в Queue действительно блокирует. Использование его с тайм-аутом может потенциально решить вашу проблему, но это определенно не будет самым чистым решением и, что наиболее важно, создаст дополнительную задержку без веской причины. Даже если это не было блокировкой, это тоже не будет хорошим решением. Просто потому, что неблокирование само по себе недостаточно, хороший асинхронный вызов / API должен плавно интегрироваться в используемую инфраструктуру ввода-вывода. Будь таким Gevent для Python, libevent для C или Boost ASIO для C ++.

Самым простым решением было бы использовать простой ввод-вывод, вызывая ваши консольные приложения и подключая к консоли дескрипторы входа и выхода. Есть два основных фактора, которые следует учитывать:

  • Вашим клиентам будет очень легко писать клиентские приложения. Им не придется работать с каким-либо IPC, сокетом или другим кодом, что может быть очень сложным для многих. При таком подходе приложение будет просто читать из стандартного ввода и писать в стандартный вывод.
  • С этим подходом будет очень легко тестировать консольные приложения, так как вы можете запустить их вручную, ввести текст в консоль и увидеть результаты.
  • Gevent идеально подходит для асинхронного чтения / записи здесь.

Однако недостатком является то, что вам придется запускать это приложение, не будет поддержки одновременного взаимодействия с ним и не будет поддержки связи по сети. Есть даже хороший пример для начинающих .

Чтобы сделать его простым, но более гибким, вы можете использовать сокеты TCP / IP. Если и клиент, и сервер работают на одном компьютере. Кроме того, хорошая операционная система будет использовать IPC в качестве базовой реализации, поэтому она будет быстрой. И, если вы беспокоитесь о производительности этого случая, вам, вероятно, вообще не следует использовать Python и смотреть на другие технологии.

Решение даже для фантазий - используйте ZeroC ICE . Это очень современная технология, обеспечивающая практически бесшовное взаимодействие между процессами. Это убийца CORBA, очень прост в использовании. Он активно используется многими, зарекомендовал себя как самый быстрый в своем классе и стабильный. Прелесть этого решения в том, что вы можете легко интегрировать программы на разных языках, таких как Python, Java, C ++ и т. Д. Но для этого потребуется некоторое время, чтобы ознакомиться с концепцией. Если вы решили пойти по этому пути, просто потратьте день на чтение документации.

Надеюсь, это поможет. Удачи!

0 голосов
/ 12 февраля 2013

Ваш вопрос уже довольно старый. Тем не менее, я хотел бы порекомендовать http://gehrcke.de/gipc, который, как я полагаю, решит поставленную задачу очень простым способом. По сути, это позволяет вам интегрировать многопроцессорные дочерние процессы в любом месте вашего приложения (также в Windows). Взаимодействие с Process объектами (например, вызов join()) является совместным с Gevent. Посредством управления каналом он позволяет совместно блокировать межпроцессное взаимодействие. Однако в Windows IPC в настоящее время намного менее эффективен, чем в POSIX-совместимых системах (поскольку неблокирующий ввод-вывод имитируется через пул потоков). В зависимости от объема сообщений IPC вашего приложения, это может иметь или не иметь значение.

...