Calling Python in Java

Calling Python in Java?

Jython: Python for the Java Platform - http://www.jython.org/index.html

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

Calling Java from Python

Here is my summary of this problem: 5 Ways of Calling Java from Python

http://baojie.org/blog/2014/06/16/call-java-from-python/ (cached)

Short answer: Jpype works pretty well and is proven in many projects (such as python-boilerpipe), but Pyjnius is faster and simpler than JPype

I have tried Pyjnius/Jnius, JCC, javabridge, Jpype and Py4j.

Py4j is a bit hard to use, as you need to start a gateway, adding another layer of fragility.

Call and receive output from Python script in Java?

Not sure if I understand your question correctly, but provided that you can call the Python executable from the console and just want to capture its output in Java, you can use the exec() method in the Java Runtime class.

Process p = Runtime.getRuntime().exec("python yourapp.py");

You can read up on how to actually read the output from this resource:
http://www.devdaily.com/java/edu/pj/pj010016
import java.io.*;

public class JavaRunCommand {

public static void main(String args[]) {

String s = null;

try {

// run the Unix "ps -ef" command
// using the Runtime exec method:
Process p = Runtime.getRuntime().exec("ps -ef");

BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));

BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));

// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}

// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}

System.exit(0);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
}
}

There is also an Apache library (the Apache exec project) that can help you with this. You can read more about it here:

http://www.devdaily.com/java/java-exec-processbuilder-process-1

http://commons.apache.org/exec/

Run Python script through Java with importing just once

You could communicate between java and Python with pipes.

You run your Python as you do now (without command line args)

Python script

you write an infinite loop in python that will


  1. read data from the
    standard input (it will be your arg for the function)

  2. You call your function

  3. you write the answer to the standard output

Java

  1. Write a method for sending args to python

  2. write to the pipe the arg of your function

  3. read the answer from the pipe

You're done.

Here is some snippet

Here how you create your tube

        Process p = Runtime.getRuntime().exec(commande);
BufferedReader output = getOutput(p); //from python to java
BufferedReader error = getError(p); //from python to java
PrintWriter input = getInput(p); //from java to python

private static BufferedReader getOutput(Process p) {
return new BufferedReader(new InputStreamReader(p.getInputStream()));
}
private static BufferedReader getError(Process p) {
return new BufferedReader(new InputStreamReader(p.getErrorStream()));
}
private static PrintWriter getInput(Process p){
return new PrintWriter (new OutputStreamWriter(p.getOutputStream()));
}

How to call a Python script with arguments from Java class

Have you looked at these? They suggest different ways of doing this:

Call Python code from Java by passing parameters and results

How to call a python method from a java class?

In short one solution could be:

public void runPython() 
{ //need to call myscript.py and also pass arg1 as its arguments.
//and also myscript.py path is in C:\Demo\myscript.py

String[] cmd = {
"python",
"C:/Demo/myscript.py",
this.arg1,
};
Runtime.getRuntime().exec(cmd);
}

edit: just make sure you change the variable name from str to something else, as noted by cdarke

Your python code (change str to something else, e.g. arg and specify a path for file):

def returnvalue(arg) :
if arg == "hi" :
return "yes"
return "no"
print("calling python function with parameters:")
print(sys.argv[1])
arg = sys.argv[1]
res = returnvalue(arg)
print(res)
with open("C:/path/to/where/you/want/file.txt", 'w') as target: # specify path or else it will be created where you run your java code
target.write(res)

calling python from java

Currently jython does not support native compiled python modules. In order to run native modules you will need access to a native python(cpython) interpreter from java. There are several open source projects that use JNI to access a cpython interpreter. Three projects that you can look into are JEP, JPY, and JyNI. In regards to GPU access, I only have experience with JEP which I have used with PyCUDA to execute code on the GPU. While I don't have personal experience with tensorflow, I know there are posts on the JEP mailing list regarding using JEP and tensorflow so I believe there are other projects using this combination successfully.

Issue in calling Python code from Java (without using jython)

I think you could try your luck with the ProcessBuilder class.

If I read the Oracle documentation correctly, the std inputs and outputs are directed to pipes by default but the ProcessBuilder has an easy method for you to explicitly set output (or input) to a file on your system or something else.

If you want your Python program to use the same output as your Java program (likely stdout and stderr), you can use stg like this:

ProcessBuilder pb = new ProcessBuilder("C:\\Python\\Python36-32\\python.exe", "C:\\test2.py");
pb.redirectOutput(Redirect.INHERIT);
Process p = pb.start();

Repeatedly calling python from Java in the most efficient way

Rather than launching each program separately and running to completion, create a "launcher" that reads from standard input, and interact with that launcher - this should be a program that won't exit until it's told to; its entire purpose is to launch other functions.

Then treat it as a resource and use it to call the individual functions and return results (rather than Java's Process).

The same strategy can be used for many different types of external programs that have shared dependencies - the launcher can load the common dependencies/ it's own runtime once, and more quickly call functions in those dependencies.

Different / better approaches for calling python function from Java

There is no current answer to this problem. Using CPython relies on the execution of Python bytecodes, which in turn requires that the Python interpreter be embedded in the execution environment. Since no Java runtime comes with an embedded Python interpreter, it really does look as though Jython is the best answer.

Sometimes the answer you want just isn't available!

Calling Python scripts from Java. Should I use Docker?

You don’t need docker for this. There are a couple of options, you should choose depending on what your Java application is doing.

  1. If the Java application is a client - based on swing, weblaunch, or providing UI directly - you will want to turn the python functionality to be wrapped in REST/HTTP calls.

  2. If the Java application is a server/webapp - executing within Tomcat, JBoss or other application container - you should simply wrap the python scrip inside a exec call. See the Java Runtime and ProcessBuilder API for this purpose.



Related Topics



Leave a reply



Submit