Py4J – мост между Python и Java

от автора

Название Py4J можно встретить разве что в списке библиотек, используемых PySpark, но не стоит недооценивать данный инструмент, который обеспечивает совместную работу Python и Java. В этой статье будет кратко описана работа Py4J, рассмотрен пример использования и перечислены сильные и слабые стороны библиотеки. В конце будут описаны альтернативные способы связи Java и Python.

Py4J позволяет программам, работающим в интерпретаторе Python, динамически обращаться к объектам Java внутри JVM. Методы вызываются так, как если бы объекты Java находились в интерпретаторе Python, а доступ к коллекциям Java можно было получить с помощью стандартных методов коллекций Python. Py4J также позволяет программам Java вызывать объекты Python, но на этом возможности библиотеки не заканчиваются. Py4J позволяет создавать из Python классические коллекции Java, а именно Array, List, Set и Map. Также можно конвертировать Python коллекции в Java коллекции. Ещё из Python возможно реализовывать интерфейсы, которые описаны в Java.

Существует несколько альтернатив, например, Jython. В отличие от него, Py4J не выполняет код Python в JVM, поэтому при использовании Py4J можно работать со всеми библиотеками классического Cython. Ещё есть JPype, но Py4J не связывает потоки Python и Java, также он использует сокеты, а не JNI для связи с JVM.

Главным минусом Py4J является скорость передачи данных между Python и Java. Так как общение происходит посредством сокетов, передавать данные, размером больше чем несколько мегабайт, будет плохой идеей, для этой цели существуют другие решения. Главная задача Py4J – обеспечить доступ к объектам Java и сохранить возможность использования Python библиотек.

Пример работы

Для примера будет создано три Java класса и один Python скрипт для проверки работы. Класс Dict, в котором реализована логика работы с HashMap, Класс DictEntryPoint, в котором реализована точка входа, чтобы Python мог взаимодействовать с объектом класса Dict. Также нужен класс Program, в котором происходит запуск сервера.

Для успешной работы Py4J нужно настроить точку входа, в которой создать необходимые для работы объекты, и запустить GatewayServer, который обеспечивает связь Python с JVM через сокет локальной сети. Далее можно спокойно использовать Java код из Python.

Dict.java

  package py4j_example;    import java.util.HashMap;    public class Dict {     private HashMap<Integer, String> dict = new HashMap<>();      /**     * Добавление элемента по ключу     */     public void add(Integer key, String value) {          dict.put(key, value);      }      /**     * Добавляет значение в конец HashMap     */     public void add(String value) {         dict.put(dict.size(), value);     }      /**     * Удаляет значение по ключу     */     public String remove(Integer key) {         return dict.remove(key);     }      /**     * Возвращает значение по ключу     */     public String get(Integer key) {         return dict.get(key);     }      /**     * Возвращает длину HashMap     */     public int length() {         return dict.size();     }      /**     * Пересоздаёт HashMap     */     public void clear() {         dict = new HashMap<>();         add("Запись из Java");     }   } 

DictEntryPoint.java

  package py4j_example;    import py4j.GatewayServer;    public class DictEntryPoint {     private final Dict dict;      /**     * Создаёт объект класса Dict     */     public DictEntryPoint() {         this.dict = new Dict();     }      /**     * Возвращает объект класса Dict     */     public Dict getDict() {         return this.dict;     }   } 

Program.java

  package py4j_example;    import py4j.GatewayServer;    public class Program {     public static void main(String[] args) {       /* Создание и запуск сервера */       GatewayServer gatewayServer = new GatewayServer(new DictEntryPoint());       gatewayServer.start();       System.out.println("Gateway Server Started");     }   } 

Вывод должен быть примерно такой. После запуска Program.java можно приступить к написанию Python кода для подключения к JVM.

  Connected to the target VM, address: '127.0.0.1:58425', transport: 'socket'   Gateway Server Started 

Application.py

  from py4j.java_gateway import JavaGateway      def add_some_values(dict):     # Создание списка имён и их запись в dict     names = ["Вася", "Аня", "Лена", "Никита"]     for name in names:         dict.add(name)      # Удаление значения по ключу 4     deleted = dict.remove(4)      # Вывод содержимого dict     for i in range(dict.length()):         print(i, "\t", dict.get(i))      print("\nУдалённый элемент =", deleted)     return 1    def main():     # Инициализация JavaGateway     gateway = JavaGateway()     # Получение доступа к объекту класса Dict     dict = gateway.entry_point.getDict()      add_some_values(dict)     # Очистка Dict     dict.clear()     return 0    if __name__ == "__main__":       main() 

После запуска Application.py в консоль выводится следующее:

  0 Запись из Java   1 Вася   2 Аня   3 Лена    Удалённый элемент = Никита 

По ключу 0 находится элемент, добавленный из Java, а имена людей были добавлены с помощью Python.

Заключение

Py4J позволяет быстро и легко взаимодействовать с объектами Java из Python, организовывать двустороннее управление коллекциями и работать с интерфейсами в двух языках, соединяя интерпретатор и JVM сокетами. Он отлично подойдёт для задач, требующих минимальных ограничений на использование Python, но при этом не отличается высокой производительностью.


На правах рекламы

VDSina предлагает быстрые серверы в аренду под любые задачи, огромный выбор операционных систем для автоматической установки, есть возможность установить любую ОС с собственного ISO, удобная панель управления собственной разработки и посуточная оплата.

Подписывайтесь на наш чат в Telegram.

ссылка на оригинал статьи https://habr.com/ru/company/vdsina/blog/555140/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *