Взаимодействие интерпретаторов Python-IronPython-Jython

в 7:40, , рубрики: .net, ironpython, java, jython, python, межпроцессное взаимодействие, метки: , , , , ,

Возникла необходимость в решении такой задачи: как обмениваться данными между разными интерпретаторами Python?! Отыскал несколько решений, но хочу рассказать об одном, на мой взгляд, самом удобном.

Выбор подхода

Для начала я пытался выбрать наиболее удобное решение из множества. Может не корректно сравнивать message queue, сокеты и RPC, но я исходил от задачи. Вот что доступно:

Сокеты TCP

Использование сокетов, наиболее простой способ взаимодействия, можно передавать любые данные, но код придётся насыщать реализацией собственного протокола. Этот путь тернист, и ошибки неизбежны. Вывод: подходит, но сложно.

Библиотека ZeroMQ

Очень перспективная разработка brokerless очередь сообщений. Реализована как библиотека pyzmq и pyzmq-static. Для первого случая нужно установить саму ZeroMQ — написанная на C разделяемая библиотека. Вторая уже содержит бинарник. Начиналось всё весьма забавно, код работал отлично, пока я не перешёл к IronPython…
Для IronPython pyzmq не реализована, но не проблема, есть же .NET Integration, что позволяет использовать clrzmq — биндинг для .NET; и вот здесь начались проблемы. Бинарник доступен через плагин для VisualStudio — nuget, поэтому пришлось бибилотеку компилировать.Скачал исходник, там всё удобно, скрипт собирается командой build, но не всё так просто. Версия 2 не собралась вообще, хотя зависимости разрешила через nuget корректно (может взял битый commit?), 3 бета собралась, но падала даже на примере из tutorial )
В итоге и сети отыскал бинарник 2-ки, но это меня совсем не порадовало. Всё заработало, но API в 3-ке так сильно изменился, что не хотелось потом переписывать код по сто раз. Вывод: хорошо, но сыро вне чистого Python.

Pyro, поджигай!

Поначалу решил добивать 0mq, но вспомнил о сущеcтвовании такой библиотеки как Pyro: библиотеки из кризисных 90-х, которая прекрасно поживает и развивается. Не буду перечислять все её плюсы, сейчас интересует только один — взаимодействие интерпретаторов. Сразу к делу, пробуем пример из tutorial, но с той разницей, что запускаем всё под разными интерпретаторами (код не менял, только вписал свой ник).

Запускаем сервер имён под Jython, кстати, вот и первый огромный плюс, у 0mq сервер имён ещё не доделан:
Взаимодействие интерпретаторов Python IronPython Jython
Ого! Завелось...

Теперь регистрируем сервер, который будет работать под IronPython:
Взаимодействие интерпретаторов Python IronPython Jython
Регистрация прошла успешно.

Следующий шаг, запуск клиента. Делаем под классическим питоном (у меня их сразу много стоит, но запускал EPD):
Взаимодействие интерпретаторов Python IronPython Jython
Прекрасно! Всё сработало.

Версия pickle

Как вариант, попробовал ещё запускать одну из частей под Python 3. Без хака не сработало :( Последний использует pickle третьей версии + нет некоторых стандартных модулей (удалены, перенесены), хотя это поведение можно обойти. Но главная причина, Pyro4 иcпользует pickle для сериализации, при этом самую последнюю версию. Вот как удалось обойти этот недостаток и подключиться Python 3 к IronPython 2 и Jython 2:

import pickle
pickle.HIGHEST_PROTOCOL = 2

Это нужно добавить в код клиента перед импортом Pyro. Всё сработало:
Взаимодействие интерпретаторов Python IronPython Jython
Обратите внимание на использование 64-битного Python.

Кстати, как вариант, можно использовать библиотеку pyrolite для прямого подключения из .NET или Java без Python интерпретатора. Это фактически мини pickle.

В целом решение с Pyro пока понравилось больше других, если же система содержит очень много компонент разных версий, то, наверное, выгоднее будет использовать 0mq. Хотя я пока остановлюсь всё же на Pyro4.

Автор: deko


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js