How to Call Python From Java

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

1. Overview

Python is an increasingly popular programming language, particularly in the scientific community due to its rich variety of numerical and statistical packages. Therefore, it's not an uncommon requirement to able to invoke Python code from our Java applications.

In this tutorial, we'll take a look at some of the most common ways of calling Python code from Java.

2. A Simple Python Script

Throughout this tutorial, we'll use a very simple Python script which we'll define in a dedicated file called hello.py:

print("Hello Baeldung Readers!!")

Assuming we have a working Python installation, when we run our script we should see the message printed:

$ python hello.py
Hello Baeldung Readers!!

3. Core Java

In this section, we'll take a look at two different options we can use to invoke our Python script using core Java.

3.1. Using ProcessBuilder

Let's first take a look at how we can use the ProcessBuilder API to create a native operating system process to launch python and execute our simple script:

In this first example, we're running the python command with one argument which is the absolute path to our hello.py script. We can find it in our test/resources folder.

To summarize, we create our ProcessBuilder object passing the command and argument values to the constructor. It's also important to mention the call to redirectErrorStream(true). In case of any errors, the error output will be merged with the standard output.

This is useful as it means we can read any error messages from the corresponding output when we call the getInputStream() method on the Process object. If we don't set this property to true, then we'll need to read output from two separate streams, using the getInputStream() and the getErrorStream() methods.

Now, we start the process using the start() method to get a Process object. Then we read the process output and verify the contents is what we expect.

As previously mentioned, we've made the assumption that the python command is available via the PATH variable.

3.2. Working With the JSR-223 Scripting Engine

JSR-223, which was first introduced in Java 6, defines a set of scripting APIs that provide basic scripting functionality. These methods provide mechanisms for executing scripts and for sharing values between Java and a scripting language. The main objective of this standard was to try to bring some uniformity to interoperating with different scripting languages from Java.

We can use the pluggable script engine architecture for any dynamic language provided it has a JVM implementation, of course. Jython is the Java platform implementation of Python which runs on the JVM.

Assuming that we have Jython on the CLASSPATH, the framework should automatically discover that we have the possibility of using this scripting engine and enable us to ask for the Python script engine directly.

Since Jython is available from Maven Central, we can just include it in our pom.xml:

As we can see, it is pretty simple to work with this API. First, we begin by setting up a ScriptContext which contains a StringWriter. This will be used to store the output from the script we want to invoke.

We then use the getEngineByName method of the ScriptEngineManager class to look up and create a ScriptEngine for a given short name. In our case, we can pass python or jython which are the two short names associated with this engine.

As before, the final step is to get the output from our script and check it matches what we were expecting.

4. Jython

Continuing with Jython, we also have the possibility of embedding Python code directly into our Java code. We can do this using the PythonInterpretor class:

This example is not too dissimilar to our first example using ProcessBuilder. We create a CommandLine object for our given command. Next, we set up a stream handler to use for capturing the output from our process before executing our command.

To summarize, the main philosophy behind this library is to offer a process execution package aimed at supporting a wide range of operating systems through a consistent API.

6. Utilizing HTTP for Interoperability

Let's take a step back for a moment and instead of trying to invoke Python directly consider using a well-established protocol like HTTP as an abstraction layer between the two different languages.

In actual fact Python ships with a simple built-in HTTP server which we can use for sharing content or files over HTTP:

python -m http.server 9000

If we now go to http://localhost:9000, we'll see the contents listed for the directory where we launched the previous command.

Some other popular frameworks we could consider using for creating more robust Python-based web services or applications are Flask and Django.

Once we have an endpoint we can access, we can use any one of several Java HTTP libraries to invoke our Python web service/application implementation.

7. Conclusion

In this tutorial, we've learned about some of the most popular technologies for calling Python code from Java.

As always, the full source code of the article is available over on GitHub.

Java bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2: