CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-python--jython-standalone

Jython is an implementation of Python 2.7 written in 100% Pure Java, providing seamless integration with the Java platform and ecosystem.

Pending
Overview
Eval results
Files

java-integration.mddocs/

Java-Python Integration

Jython provides seamless integration between Java and Python, allowing automatic type conversion, method invocation, and exception handling across both platforms.

Type Conversion

Java to Python Conversion

Automatic conversion from Java objects to Python objects.

public final class Py {
    // Generic conversion
    public static PyObject java2py(Object o);
    
    // Specific conversions
    public static PyString java2py(String s);
    public static PyInteger java2py(int i);
    public static PyInteger java2py(long l);
    public static PyFloat java2py(float f);
    public static PyFloat java2py(double d);
    public static PyBoolean java2py(boolean b);
    public static PyObject java2py(Object o);
}

Python to Java Conversion

Convert Python objects back to Java types.

public abstract class PyObject {
    // Generic conversion
    public Object __tojava__(Class<?> c);
    
    // Common conversions available on specific types
    public String toString();
    public boolean equals(Object o);
    public int hashCode();
}

// Specific conversion methods on respective classes
public class PyString {
    public String getString();
    public String asString();
}

public class PyInteger {
    public int getValue();
    public int asInt();
    public long asLong();
    public double asDouble();
}

public class PyFloat {
    public double getValue();
    public double asDouble();
    public int asInt();
}

public class PyBoolean {
    public boolean getBooleanValue();
    public boolean __bool__();
}

Usage Examples

Basic Type Conversion

// Java to Python
String javaStr = "Hello, World!";
PyString pyStr = Py.java2py(javaStr);

int javaInt = 42;
PyInteger pyInt = Py.java2py(javaInt);

double javaDouble = 3.14159;
PyFloat pyFloat = Py.java2py(javaDouble);

boolean javaBool = true;
PyBoolean pyBool = Py.java2py(javaBool);

// Python to Java
String backToJava = pyStr.getString();
int backToInt = pyInt.asInt();
double backToDouble = pyFloat.asDouble();
boolean backToBool = pyBool.getBooleanValue();

Collection Conversion

// Java List to Python List
List<String> javaList = Arrays.asList("apple", "banana", "cherry");
PyList pyList = new PyList();
for (String item : javaList) {
    pyList.append(Py.java2py(item));
}

// Python List to Java List
List<String> backToJavaList = new ArrayList<>();
for (int i = 0; i < pyList.__len__(); i++) {
    PyObject item = pyList.__getitem__(i);
    backToJavaList.add(item.toString());
}

Map Conversion

// Java Map to Python Dictionary
Map<String, Object> javaMap = new HashMap<>();
javaMap.put("name", "Alice");
javaMap.put("age", 30);
javaMap.put("active", true);

PyDictionary pyDict = new PyDictionary();
for (Map.Entry<String, Object> entry : javaMap.entrySet()) {
    PyString key = Py.java2py(entry.getKey());
    PyObject value = Py.java2py(entry.getValue());
    pyDict.put(key, value);
}

// Python Dictionary to Java Map
Map<String, Object> backToJavaMap = new HashMap<>();
PyList keys = pyDict.keys();
for (int i = 0; i < keys.__len__(); i++) {
    PyObject key = keys.__getitem__(i);
    PyObject value = pyDict.get(key);
    backToJavaMap.put(key.toString(), value.__tojava__(Object.class));
}

Java Object Access from Python

Accessing Java Objects in Python Code

PythonInterpreter interp = new PythonInterpreter();

// Make Java objects available to Python
ArrayList<String> javaList = new ArrayList<>();
javaList.add("item1");
javaList.add("item2");
interp.set("java_list", javaList);

// Access Java methods from Python
interp.exec("""
    print("Java list size:", java_list.size())
    java_list.add("item3")
    for item in java_list:
        print("Item:", item)
    """);

interp.close();

Java Class Access

PythonInterpreter interp = new PythonInterpreter();

// Import Java classes
interp.exec("""
    from java.util import ArrayList, HashMap
    from java.lang import System
    
    # Create Java objects
    list = ArrayList()
    list.add("Hello")
    list.add("World")
    
    map = HashMap()
    map.put("key1", "value1")
    map.put("key2", "value2")
    
    # Call Java static methods
    System.out.println("From Python: " + str(list))
    """);

interp.close();

Python Object Proxy Classes

Jython provides proxy classes for seamless Java-Python integration.

JavaProxyList

public class JavaProxyList extends PySequenceList implements List {
    public JavaProxyList(List list);
    
    // Implements both Python sequence protocol and Java List interface
    public boolean add(Object o);
    public void add(int index, Object element);
    public boolean remove(Object o);
    public Object remove(int index);
    public Object get(int index);
    public Object set(int index, Object element);
    public int size();
    public boolean isEmpty();
    public void clear();
}

JavaProxyMap

public class JavaProxyMap extends AbstractDict implements Map {
    public JavaProxyMap(Map map);
    
    // Implements both Python mapping protocol and Java Map interface
    public Object put(Object key, Object value);
    public Object get(Object key);
    public Object remove(Object key);
    public boolean containsKey(Object key);
    public Set keySet();
    public Collection values();
    public Set entrySet();
    public int size();
    public boolean isEmpty();
    public void clear();
}

Usage Examples

// Wrap Java collections for Python use
List<String> javaList = new ArrayList<>();
JavaProxyList proxyList = new JavaProxyList(javaList);

PythonInterpreter interp = new PythonInterpreter();
interp.set("proxy_list", proxyList);

interp.exec("""
    # Use as Python list
    proxy_list.append("Hello")
    proxy_list.append("World")
    print("Length:", len(proxy_list))
    for item in proxy_list:
        print(item)
    """);

// Changes are reflected in original Java list
System.out.println("Java list: " + javaList);

interp.close();

Method Invocation

Calling Python Functions from Java

PythonInterpreter interp = new PythonInterpreter();

// Define Python function
interp.exec("""
    def greet(name, age=None):
        if age:
            return f"Hello, {name}! You are {age} years old."
        else:
            return f"Hello, {name}!"
    """);

// Get function object
PyObject greetFunc = interp.get("greet");

// Call with positional arguments
PyObject result1 = greetFunc.__call__(new PyObject[]{Py.newString("Alice")});
System.out.println(result1); // Hello, Alice!

// Call with keyword arguments
PyObject result2 = greetFunc.__call__(
    new PyObject[]{Py.newString("Bob"), Py.newInteger(30)},
    new String[]{"name", "age"}
);
System.out.println(result2); // Hello, Bob! You are 30 years old.

interp.close();

Calling Java Methods from Python

PythonInterpreter interp = new PythonInterpreter();

// Define Java class with methods
class Calculator {
    public static int add(int a, int b) {
        return a + b;
    }
    
    public int multiply(int a, int b) {
        return a * b;
    }
}

// Make Java class available
interp.set("Calculator", Calculator.class);
interp.set("calc_instance", new Calculator());

interp.exec("""
    # Call static method
    result1 = Calculator.add(5, 3)
    print("5 + 3 =", result1)
    
    # Call instance method
    result2 = calc_instance.multiply(4, 7)
    print("4 * 7 =", result2)
    """);

interp.close();

Exception Integration

Python Exceptions in Java

PythonInterpreter interp = new PythonInterpreter();

try {
    interp.exec("raise ValueError('Something went wrong')");
} catch (PyException e) {
    // Check exception type
    if (e.match(Py.ValueError)) {
        System.out.println("Caught ValueError: " + e.value);
    }
    
    // Get exception details
    PyObject excType = e.type;
    PyObject excValue = e.value;
    PyTraceback traceback = e.traceback;
    
    System.out.println("Exception type: " + excType);
    System.out.println("Exception value: " + excValue);
}

interp.close();

Java Exceptions in Python

class RiskyClass {
    public static void riskyMethod() throws IOException {
        throw new IOException("File not found");
    }
}

PythonInterpreter interp = new PythonInterpreter();
interp.set("RiskyClass", RiskyClass.class);

interp.exec("""
    try:
        RiskyClass.riskyMethod()
    except Exception as e:
        print("Caught Java exception:", type(e).__name__)
        print("Message:", str(e))
    """);

interp.close();

Advanced Integration Patterns

Custom Type Adapters

Jython provides adapter mechanisms for custom type conversion:

public interface ClassicPyObjectAdapter {
    public Object adapt(PyObject o);
    public PyObject adapt(Object o);
    public boolean canAdapt(Object o);
}

public interface ExtensiblePyObjectAdapter {
    public Object adapt(PyObject o);
    public PyObject adapt(Object o);
    public boolean canAdapt(Object o);
}

Bean Property Access

Java beans can be accessed using Python attribute syntax:

class Person {
    private String name;
    private int age;
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

PythonInterpreter interp = new PythonInterpreter();
interp.set("person", new Person());

interp.exec("""
    # Access bean properties as Python attributes
    person.name = "Alice"
    person.age = 30
    
    print(f"Name: {person.name}")
    print(f"Age: {person.age}")
    """);

interp.close();

Iterator Integration

Java iterables work seamlessly with Python iteration:

List<String> items = Arrays.asList("apple", "banana", "cherry");

PythonInterpreter interp = new PythonInterpreter();
interp.set("items", items);

interp.exec("""
    # Iterate over Java list using Python syntax
    for item in items:
        print("Item:", item)
    
    # Use with Python list comprehensions
    upper_items = [item.upper() for item in items]
    print("Upper case:", upper_items)
    """);

interp.close();

Performance Considerations

Minimizing Conversions

// Avoid repeated conversions
// Bad:
for (int i = 0; i < 1000; i++) {
    PyObject pyInt = Py.java2py(i);
    // use pyInt
}

// Better:
PyObject[] pyInts = new PyObject[1000];
for (int i = 0; i < 1000; i++) {
    pyInts[i] = Py.java2py(i);
}

Reusing Objects

// Reuse common objects
PyString separator = Py.newString(",");
PyList result = Py.newList();

for (String item : items) {
    if (result.__len__() > 0) {
        result.append(separator);
    }
    result.append(Py.java2py(item));
}

Thread Safety

Type conversion operations are generally thread-safe, but be careful with:

  • Shared PyObject instances
  • Concurrent access to mutable Python objects
  • System state modifications
// Thread-safe pattern
public class ThreadSafeConverter {
    private static final ThreadLocal<PythonInterpreter> INTERPRETER = 
        ThreadLocal.withInitial(() -> PythonInterpreter.threadLocalStateInterpreter(null));
    
    public PyObject convert(Object javaObj) {
        return Py.java2py(javaObj);
    }
    
    public Object convert(PyObject pyObj, Class<?> targetClass) {
        return pyObj.__tojava__(targetClass);
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-python--jython-standalone

docs

configuration.md

exception-handling.md

index.md

java-integration.md

jsr223-scripting.md

python-execution.md

python-objects.md

tile.json