Use python with java

How to call a python method from a java class?

Now the problem is I want to call the abc() method of my Python file from the myMethod method of my Java file and print the result.

4 Answers 4

If I read the docs right, you can just use the eval function:

interpreter.execfile("/path/to/python_file.py"); PyDictionary result = interpreter.eval("myPythonClass().abc()"); 

Or if you want to get a string:

PyObject str = interpreter.eval("repr(myPythonClass().abc())"); System.out.println(str.toString()); 

If you want to supply it with some input from Java variables, you can use set beforehand and than use that variable name within your Python code:

interpreter.set("myvariable", Integer(21)); PyObject answer = interpreter.eval("'the answer is: %s' % (2*myvariable)"); System.out.println(answer.toString()); 

@ashti: Yeah, that would supply myvariable as an argument to the abc method of your class. I added another example to demonstrate how to use that newly created variable.

@hasti: In that case you are invited to accept the answer by clicking at the tick on the left side 😉

Sorry but my reputation is low to do so. Also could you help me in converting PyObject to boolean type in java?

If we need to run a python function that has parameters, and return results, we just need to print this:

import org.python.core.PyObject; import org.python.core.PyString; import org.python.util.PythonInterpreter; public class method < public static void main(String[] args) < PythonInterpreter interpreter = new PythonInterpreter(); interpreter.execfile("/pathtoyourmodule/somme_x_y.py"); PyObject str = interpreter.eval("repr(somme(4,5))"); System.out.println(str.toString()); >

somme is the function in python module somme_x_y.py

There isn’t any way to do exactly that (that I’m aware of).

You do however have a few options:

1) Execute the python from within java like this:

try < String line; Process p = Runtime.getRuntime().exec("cmd /c dir"); BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream())); BufferedReader bre = new BufferedReader(new InputStreamReader(p.getErrorStream())); while ((line = bri.readLine()) != null) < System.out.println(line); >bri.close(); while ((line = bre.readLine()) != null) < System.out.println(line); >bre.close(); p.waitFor(); System.out.println("Done."); > catch (Exception err)

2) You can maybe use Jython which is «an implementation of the Python programming language written in Java», from there you might have more luck doing what you want.

3) You can make the two applications communicate somehow, with a socket or shared file

Источник

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.

Читайте также:  Python format json pretty

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

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

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

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

 package py4j_example; import java.util.HashMap; public class Dict < private HashMapdict = 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"); > > 
 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; >> 
 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 
 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, удобная панель управления собственной разработки и посуточная оплата.

Читайте также:  Parse xlsx with php

Источник

Calling Python in Java?

I am wondering if it is possible to call Python functions from Java code using Jython, or is it only for calling Java code from Python?

13 Answers 13

You can easily call python functions from Java code with Jython. That is as long as your python code itself runs under jython, i.e. doesn’t use some c-extensions that aren’t supported.

If that works for you, it’s certainly the simplest solution you can get. Otherwise you can use org.python.util.PythonInterpreter from the new Java6 interpreter support.

A simple example from the top of my head — but should work I hope: (no error checking done for brevity)

PythonInterpreter interpreter = new PythonInterpreter(); interpreter.exec("import sys\nsys.path.append('pathToModules if they are not there by default')\nimport yourModule"); // execute a function that takes a string and returns a string PyObject someFunc = interpreter.get("funcName"); PyObject result = someFunc.__call__(new PyString("Test!")); String realResult = (String) result.__tojava__(String.class); 

As of 2021, Jython does not support Python 3.x

I’ve installed JYthon, or i assume i did, and I keep trying to run the code that you outlined but it highlighted as a mistake. Does the installion of Jython need to go to a specific folder, either in the python or java folders?

If there’s no error it would work, so that’s obviously not the case 😉 «Error» does not mean runtime error, could be a compile error as well.

Python 2 end of Life is 1.1.2020 and Jython only supports Python 2.7. so no Jython is basically dead. Best (simplest) Option is the Jep lib

I think there are some important things to consider first with how strong you wish to have the linking between Java and Python.

Firstly Do you only want to call functions or do you actually want Python code to change the data in your java objects? This is very important. If you only want to call some Python code with or without arguments, then that is not very difficult. If your arguments are primitives it makes it even more easy. However, if you want to have Java class implement member functions in Python, which change the data of the Java object, then this is not so easy or straight forward.

Secondly are we talking CPython, or will Jython do? I would say CPython is where its at! I would advocate this is why Python is so kool! Having such high abstractions however access to C or C++ when needed. Imagine if you could have that in Java. This question is not even worth asking if Jython is ok because then it is easy anyway.

So I have played with the following methods, and listed them from easy to difficult:

Java to Jython

Advantages: Trivially easy. Have actual references to Java objects

Disadvantages: No CPython, Extremely Slow!

Jython from Java is so easy, and if this is really enough then great. However it is very slow and no CPython! Is life worth living without CPython? I don’t think so! You can easily have Python code implementing your member functions for you Java objects.

Java to Jython to CPython via Pyro

Pyro is the remote object module for Python. You have some object on a CPython interpreter, and you can send it objects which are transferred via serialization and it can also return objects via this method. Note that if you send a serialized Python object from Jython and then call some functions which change the data in its members, then you will not see those changes in Java. You just need to remember to send back the data which you want from Pyro. This, I believe, is the easiest way to get to CPython! You do not need any JNI or JNA or SWIG or . You don’t need to know any C, or C++. Kool huh?

  • Cannot change the member data of Java objects directly from Python
  • Is somewhat indirect (Jython is middle man)
Читайте также:  Java util zip inflater inflate

Java to C/C++ via JNI/JNA/SWIG to Python via Embedded interpreter (maybe using BOOST Libraries?)

OMG this method is not for the faint of heart. And I can tell you it has taken me very long to achieve this in with a decent method. Main reason you would want to do this is so that you can run CPython code which as full rein over you java object. There are major things to consider before deciding to try and breed Java (which is like a chimp) with Python (which is like a horse). Firstly if you crash the interpreter, that’s lights out for you program! And don’t get me started on concurrency issues! In addition, there is a lot of boiler, I believe I have found the best configuration to minimize this boiler but it is still a lot! So how to go about this: Consider that C++ is your middle man, your objects are actually C++ objects! Good that you know that now. Just write your object as if your program is in C++ and not Java, with the data you want to access from both worlds. Then you can use the wrapper generator called SWIG to make this accessible to java and compile a dll which you call ( System.load(dllNameHere) ) in Java. Get this working first, then move on to the hard part! To get to Python you need to embed an interpreter. Firstly I suggest doing some hello interpreter programs or this tutorial Embedding Python in C/C. Once you have that working, its time to make the horse and the monkey dance! You can send you C++ object to Python via [boost][3] . I know I have not given you the fish, merely told you where to find the fish. Some pointers to note for this when compiling.

When you compile boost you will need to compile a shared library. And you need to include and link to the stuff you need from jdk, ie jawt.lib, jvm.lib, (you will also need the client jvm.dll in your path when launching the application) As well as the python27.lib or whatever and the boost_python-vc100-mt-1_55.lib. Then include Python/include, jdk/include, boost and only use shared libraries (dlls) otherwise boost has a teary. And yeah full on I know. There are so many ways in which this can go sour. So make sure you get each thing done block by block. Then put them together.

Источник

Оцените статью