Различные / лучшие подходы для вызова функции Python из Java

Я новичок в Python и пытаюсь вызвать функцию Python из Java.

Мои основные требования следующие:

  • вызов должен быть прозрачным, в том смысле, что он не должен требовать изменения .py файл просто, чтобы позволить ему быть вызванным из Java. Мне может быть предоставлен любой файл Python с некоторыми функциями внутри него. Я должен иметь возможность вызывать любую из этих функций без необходимости изменения .py файл.
  • Я хочу иметь возможность отправлять аргументы обоих примитивных типов (int, String, floats и т. д.) или не примитивные типы (HashMap,ArrayList) из Java в функцию Python и получить обратно возвращенный объект (который может быть примитивных типов или не примитивных типов) из Python в Java. Я также использую pandas DataFrame и numpy ndarray и, следовательно, также хочу иметь возможность отправлять и получать соответствующие объекты в и из Java.
  • Я предпочитаю придерживаться CPython вместо Jython, потому что мне может потребоваться использовать более новые библиотеки, которые могут быть недоступны в Jython.

Есть несколько вариантов, которые я нашел в Интернете. Мало кто из них:

  • Используйте PythonInterpreter Jython, с помощью которого я могу вызвать функцию Python, не требуя каких-либо изменений в .py файл сценария:

    py1.py

     def square2(list):
         squares = []
         for i in list:
             squares.append(i*i)
         return squares
    

    JythonTest.groovy

     import org.python.util.PythonInterpreter
     import org.python.core.*;
    
     class JythonTest
     {
          static main(def args)
          {
              PythonInterpreter pi = new PythonInterpreter()
              pi.exec("from py1 import square2")
              PyFunction pf = (PyFunction)pi.get("square2")
              println pf.__call__(new PyList([1,2,3,4]))[2]   //9
          }
     }
    

    Я очень хорошо могу удовлетворить свои потребности. Но это не CPython.

  • Использовать ScriptEngine: это очень похоже на PythonInterpreter. Но опять же его Jython. Кроме того, в отличие от PythonInterpreter, мы не можем работать с Jython 2.5+ и не можем напрямую обращаться к PyObjects. Так что эта опция может быть очень хорошо закрыта.

  • Используйте py4j: пример поиска Cant, который минимален, как в случае с Jython PythonInterpreter
  • Используйте java2python. Но не так много информации о вызове python из java, чтобы я мог сделать вывод, могут ли мои вышеуказанные требования быть выполнены. Кто-нибудь может пролить больше света на это? Точнее, если мы сможем написать такой же минимальный код, как в Jython PythonInterpreter.
  • Используйте JPype: Однако после быстрого прохождения я чувствую, что не смогу написать столь же минимальный код, как в случае Jython PythonInterpreter. Также я почувствовал, что проект несколько не в разработке. Это?

Кажется, что Jython PythonInterpreter - лучший выбор, если я правильно понял все вышеперечисленные подходы. Я сделал ошибки, схватив их? Также есть какой-нибудь другой лучший вариант?

2 ответа

Решение

На данный момент нет ответа на эту проблему. Использование CPython зависит от выполнения байт-кодов Python, что, в свою очередь, требует, чтобы интерпретатор Python был встроен в среду выполнения. Поскольку ни одна среда исполнения Java не поставляется со встроенным интерпретатором Python, он действительно выглядит так, как будто Jython - лучший ответ.

Иногда нужный вам ответ просто не доступен!

@Mahesha999, относительно способности придерживаться CPython, что кажется важным сейчас с вашего последнего комментария:

Jep - это хороший вариант, чтобы иметь возможность запускать код Python, который использует вызовы native, например, панд, о которых вы упоминали.

Вам нужно написать некоторый код переноса, потому что Jep реализует только автоматическое преобразование между Java и Python между наиболее используемыми типами, которые pandas.DataFrame не является.

Однако, если ваш вариант использования не сложный, вы можете получить доступ к объектам Pandas как numpy.NDArray возражать DataFrame.values на вашем экземпляре dataframe, и Jep реализует преобразование в класс Java, который он встраивает для NDArray.

Вы можете вернуться к значениям Java из кода Python, который вы выполняете, используя Jep.getValue(String pythonVariableName, Class clazz)

Например

Jep jep = new Jep();
jep.eval("import my_script");
jep.eval("df = my_script.function_returning_a_dataframe()");
jep.eval("col = df.a_column.value");
NDArray myCol = jep.getValue("col", NDArray.class);

Я делаю это в проекте, который я написал в Python, и который мне нужно интегрировать как плагин в приложение Java, пока он работает.

Другие вопросы по тегам