Skip to: Site menu | Main content

"Young man," said von Neumann, "in mathematics you don't understand things, you just get used to them."

--quoted in G. Zukav The Dancing Wu Li Masters.

Using Python from Java without anyone noticing

Author:Walter Moreira
Status:(Nov 2009) Updated to work with Jython 2.5

Problem

We want to write classes in Python and to distribute them as Java classes, without the user knowing about Jython or Python.

We want to make the process of generating a Java class from Python code as straightforward as possible.

This was solved originally, in Jython 2.2 and previous versions, using the compiler jythonc. Unfortunately, such tool is now deprecated and a solution for Jython 2.5 is still in the works. The following solution aims to be a substitute until the successor of jythonc is released. It is inspired in the article Simple and Efficient Jython Object Factories

Solution

The jar file pyconnection.jar contains the full Jython distribution together with a thin wrapper which allows the following workflow.

Dan Developer is the person who writes the Python code and who wants to deliver a Java class. Ugo User is the person who uses the Java class delivered by Dan.

In this example, Dan delivers a sophisticated Java class which greets the user. The unsuspecting user will never know he is shaking hands with Python.

How Ugo uses what Dan delivers

Ugo needs:

Dan delivers a file greeter.jar and promises an interface GreeterType as:

public interface GreeterType {
    public void __init__(String name);
    public String greet(String salutation);
}

Ugo drops greeter.jar and pyconnection.jar into his classpath and uses the GreeterType as follows:

import greeter.*;
...
GreeterFactory factory = new GreeterFactory();

GreeterType g = factory.create("Ugo");
String result = g.greet("Hello")

Ugo can create any number of objects with factory.create, without any knowledge about Python.

How Dan builds greeter.jar

Dan needs:

Dan starts with a Python class or package. The Python code is completely independent from Java. It does not need to know anything about Java interfaces or Java types. Of course, it can use the full power of Java if needed, by importing any Java package that is in the classpath.

Dan has his Pyhton code in a directory structure as follows:

MyPythonProject/
 |_ Greeter.py
 |_ ... other python files and/or packages

The file Greeter.py contains the Python class Greeter:

class Greeter(object):
    def __init__(self, name):
        self.name = name
    def greet(self, salutation):
        return salutation + ", " + self.name

and it is used from Python as:

>>> from Greeter import Greeter
>>> g = Greeter('Ugo')
>>> g.greet('Hello')
'Hello, Ugo'

All the Python code the Greeter class uses must be under the directory MyPythonProject. The file pyconnection.jar already includes the full Python library. Any other third party module can be installed under MyPythonProject and added to Python's search path (the Python list sys.path).

Once the Python class is working on its own, Dan positions himself inside the directory MyPythonProject and invokes:

$ cd MyPythonProject
$ generate_wrapper.py Greeter GreeterProject
                      \_____/ \____________/
        Python   ________|          |________ Desired Java
     class name                               project name

After the execution of generate_wrapper.py the directory structure is:

|_ MyPythonProject/   <-------------------+
|_ GreeterProject/                        |
    |_ src/                               | Symbolic
        |_ greeter/                       |   link
        |   |_ GreeterType.java           |
        |   |_ GreeterFactory.java        |
        |_ python/     -------------------+
            |_ Greeter.py
            |_ ... other python files and/or packages

Dan can invoke generate_wrapper.py several times with other class names and the same Java project name, and the proper files will be added to the directory src inside GreeterProject.

Dan edits GreeterType.java to contain the declaration of the public interface for the Greeter Python class:

package greeter;
public interface GreeterType {
    public void __init__(String name);
    public String greet(String salutation);
}

And voila! Now, Dan just exports GreeterProject as a jar file, say greeter.jar, and he distributes it (see instructions to export using Eclipse). Optionally, Dan also distributes pyconnection.jar, although Ugo User is adviced to download pyconnection.jar once and to drop it in the classpath, ready to use with any number of packages that Dan distributes.

Exporting a jar file with Eclipse

These are the steps Dan follows to export a jar file from GreeterProject.

  1. Launch Eclipse.

  2. Create a project: click in File > New > Java project, select Create project from existing source, and enter the path that ends with the directory GreeterProject. Click Finish.

  3. Export a jar file: right click on GreeterProject in the Package Explorer, select Export, select Java > Jar file, click Next, select the export destination, click Finish.

    It is important to make sure that pyconnection.jar is in the classpath for the project GreeterProject before generating the jar file. If Eclipse signals compilation errors for GreeterProject, right click on it, select Build path > Configure Build path , click Add External Jars, and add pyconnection.jar.

The gory details

Here we explain some of the limitations and internals of PyConnection, in case something goes wrong and you need to debug through the wrapper around your Python class.

Warning: not all types are transparently converted between Java and Python yet. Currently, only these types are converted (more to come soon):

Java         Python
----         ------
String       String
Integer      Integer
HashTable    Dictionary
Vector       List

For the gory++ details, here is the source code of PyConnection, ready to be imported into Eclipse.

Section to be completed

Building pyconnection.jar

To build pyconnection.jar from scratch, just append the contents of the bin directory of PyConnection (containing the Java class files and some Python helper files) to the jar file of a standalone Jython installation.

 

Updated on: 04:27 PM, Thursday Nov 26, 2009