Jython is an implementation of Python 2.7 written in 100% Pure Java, providing seamless integration with the Java platform and ecosystem.
—
Jython provides comprehensive exception handling that bridges Python and Java exception systems, allowing seamless error handling across both platforms.
The main exception class that represents Python exceptions in Java.
public class PyException extends RuntimeException {
public PyObject type; // Exception type (e.g., ValueError, TypeError)
public PyObject value; // Exception value/message
public PyTraceback traceback; // Python traceback information
// Constructors
public PyException();
public PyException(PyObject type);
public PyException(PyObject type, String value);
public PyException(PyObject type, PyObject value);
public PyException(PyObject type, PyObject value, PyTraceback traceback);
// Exception matching and handling
public boolean match(PyObject exc);
public boolean match(PyObject[] excs);
public void normalize();
public PyObject getCause();
public void setCause(PyObject cause);
// Traceback handling
public void setTraceback(PyTraceback traceback);
public void tracebackHere(PyFrame frame);
public void tracebackHere(PyFrame frame, boolean isFinally);
// String representation
public String toString();
}All standard Python exceptions are available as static fields in the Py class.
public final class Py {
// Base exceptions
public static final PyObject Exception;
public static final PyObject BaseException;
public static final PyObject SystemExit;
public static final PyObject KeyboardInterrupt;
public static final PyObject GeneratorExit;
// Common exceptions
public static final PyObject TypeError;
public static final PyObject ValueError;
public static final PyObject RuntimeError;
public static final PyObject AttributeError;
public static final PyObject KeyError;
public static final PyObject IndexError;
public static final PyObject NameError;
public static final PyObject ImportError;
public static final PyObject IOError;
public static final PyObject OSError;
public static final PyObject SyntaxError;
public static final PyObject IndentationError;
public static final PyObject SystemError;
public static final PyObject MemoryError;
public static final PyObject OverflowError;
public static final PyObject ZeroDivisionError;
public static final PyObject AssertionError;
public static final PyObject LookupError;
public static final PyObject StopIteration;
// Warning types
public static final PyObject Warning;
public static final PyObject UserWarning;
public static final PyObject DeprecationWarning;
public static final PyObject SyntaxWarning;
public static final PyObject RuntimeWarning;
public static final PyObject FutureWarning;
public static final PyObject ImportWarning;
public static final PyObject UnicodeWarning;
public static final PyObject BytesWarning;
public static final PyObject ResourceWarning;
}Convenient factory methods for creating Python exceptions.
public final class Py {
// Exception creation
public static PyException TypeError(String message);
public static PyException ValueError(String message);
public static PyException RuntimeError(String message);
public static PyException AttributeError(String message);
public static PyException KeyError(String message);
public static PyException IndexError(String message);
public static PyException NameError(String message);
public static PyException ImportError(String message);
public static PyException IOError(String message);
public static PyException OSError(String message);
public static PyException SyntaxError(String message);
public static PyException SystemError(String message);
public static PyException MemoryError(String message);
public static PyException OverflowError(String message);
public static PyException ZeroDivisionError(String message);
public static PyException AssertionError(String message);
public static PyException StopIteration();
public static PyException StopIteration(String message);
// Exception creation with custom value
public static PyException makeException(PyObject type, PyObject value);
public static PyException makeException(PyObject type, PyObject value, PyTraceback traceback);
}Python traceback information for debugging.
public class PyTraceback extends PyObject {
public PyTraceback tb_next; // Next traceback frame
public PyFrame tb_frame; // Frame object
public int tb_lineno; // Line number
public PyTraceback(PyFrame frame);
public PyTraceback(PyTraceback next, PyFrame frame);
// Traceback manipulation
public void dumpStack();
public void dumpStack(StringBuilder buffer);
}import org.python.core.*;
import org.python.util.PythonInterpreter;
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);
} else if (e.match(Py.TypeError)) {
System.out.println("Caught TypeError: " + e.value);
} else {
System.out.println("Caught other exception: " + e.type + " - " + e.value);
}
// Print Python traceback
if (e.traceback != null) {
e.traceback.dumpStack();
}
}
interp.close();try {
interp.exec("undefined_variable + 1");
} catch (PyException e) {
// Check against multiple exception types
PyObject[] commonExceptions = {Py.NameError, Py.TypeError, Py.ValueError};
if (e.match(commonExceptions)) {
System.out.println("Caught common exception: " + e.type);
} else {
System.out.println("Caught unexpected exception: " + e.type);
throw e; // Re-raise if not handled
}
}try {
interp.exec("""
try:
x = 10 / 0
except ZeroDivisionError as e:
raise ValueError("Custom message") from e
""");
} catch (PyException e) {
System.out.println("Exception type: " + e.type);
System.out.println("Exception value: " + e.value);
// Get the original cause if available
PyObject cause = e.getCause();
if (cause != null && cause != Py.None) {
System.out.println("Caused by: " + cause);
}
// Print full traceback
System.out.println("Full traceback:");
System.out.println(e.toString());
}// Raise exceptions from Java code
PythonInterpreter interp = new PythonInterpreter();
// Set up Python function that calls Java
interp.exec("""
def test_function(value):
return java_function(value)
""");
// Define Java function that can raise Python exceptions
interp.set("java_function", new PyObject() {
public PyObject __call__(PyObject[] args, String[] keywords) {
if (args.length == 0) {
throw Py.TypeError("java_function() missing required argument");
}
PyObject arg = args[0];
if (arg instanceof PyInteger) {
int value = ((PyInteger) arg).getValue();
if (value < 0) {
throw Py.ValueError("value must be non-negative");
}
if (value == 0) {
throw Py.ZeroDivisionError("cannot divide by zero");
}
return Py.newInteger(100 / value);
} else {
throw Py.TypeError("expected integer argument");
}
}
});
// Test the exception handling
try {
interp.exec("result = test_function(-5)");
} catch (PyException e) {
if (e.match(Py.ValueError)) {
System.out.println("Validation error: " + e.value);
}
}// Create custom Python exception class from Java
interp.exec("""
class CustomError(Exception):
def __init__(self, message, error_code=None):
super().__init__(message)
self.error_code = error_code
""");
// Get the custom exception class
PyObject customErrorClass = interp.get("CustomError");
// Raise custom exception from Java
PyObject[] args = {Py.newString("Custom error occurred"), Py.newInteger(404)};
PyException customException = new PyException(customErrorClass,
customErrorClass.__call__(args));
throw customException;// Java method that throws checked exception
class FileProcessor {
public static String readFile(String filename) throws IOException {
if (!new File(filename).exists()) {
throw new IOException("File not found: " + filename);
}
return Files.readString(Paths.get(filename));
}
}
PythonInterpreter interp = new PythonInterpreter();
interp.set("FileProcessor", FileProcessor.class);
interp.exec("""
try:
content = FileProcessor.readFile("nonexistent.txt")
except Exception as e:
print("Caught Java exception:", type(e).__name__)
print("Message:", str(e))
# Java exceptions appear as Python exceptions
import traceback
traceback.print_exc()
""");// Automatic conversion of Java exceptions
try {
interp.exec("""
from java.lang import Integer
# This will throw NumberFormatException
num = Integer.parseInt("not_a_number")
""");
} catch (PyException e) {
// Java NumberFormatException becomes Python exception
System.out.println("Java exception as Python: " + e.type);
System.out.println("Message: " + e.value);
}import org.python.core.Options;
// Show Java stack traces in Python exceptions
Options.showJavaExceptions = true;
// Include Java stack traces in Python tracebacks
Options.includeJavaStackInExceptions = true;
// Show Python proxy exceptions
Options.showPythonProxyExceptions = true;
PythonInterpreter interp = new PythonInterpreter();
try {
interp.exec("""
from java.util import ArrayList
list = ArrayList()
# This will show Java stack trace if enabled
list.get(10) # IndexOutOfBoundsException
""");
} catch (PyException e) {
System.out.println("Exception with Java details: " + e);
}
interp.close();// Exception handling with context managers
interp.exec("""
class ExceptionHandler:
def __enter__(self):
print("Entering exception context")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type:
print(f"Handling {exc_type.__name__}: {exc_val}")
return True # Suppress exception
print("Exiting normally")
return False
""");
// Use the context manager
interp.exec("""
with ExceptionHandler():
raise ValueError("This will be suppressed")
print("Execution continues after context manager")
""");// Python-style exception chaining
try {
interp.exec("""
def inner_function():
raise ValueError("Original error")
def outer_function():
try:
inner_function()
except ValueError as e:
raise RuntimeError("Wrapper error") from e
outer_function()
""");
} catch (PyException e) {
System.out.println("Main exception: " + e.type + " - " + e.value);
// Check for chained exception
PyObject cause = e.getCause();
if (cause != null && cause != Py.None) {
System.out.println("Caused by: " + cause);
}
}public class JythonExceptionHandler {
private PythonInterpreter interp;
public JythonExceptionHandler(PythonInterpreter interp) {
this.interp = interp;
}
public Object safeExecute(String code) {
try {
return interp.eval(code);
} catch (PyException e) {
return handlePythonException(e);
} catch (Exception e) {
return handleJavaException(e);
}
}
private Object handlePythonException(PyException e) {
if (e.match(Py.SyntaxError)) {
System.err.println("Syntax error in Python code: " + e.value);
return null;
} else if (e.match(Py.NameError)) {
System.err.println("Undefined variable: " + e.value);
return null;
} else if (e.match(Py.TypeError)) {
System.err.println("Type error: " + e.value);
return null;
} else {
System.err.println("Unhandled Python exception: " + e.type + " - " + e.value);
e.printStackTrace();
return null;
}
}
private Object handleJavaException(Exception e) {
System.err.println("Java exception: " + e.getMessage());
e.printStackTrace();
return null;
}
}
// Usage:
JythonExceptionHandler handler = new JythonExceptionHandler(interp);
Object result = handler.safeExecute("undefined_variable");public class RobustJythonService {
private PythonInterpreter interp;
public String processData(String data) {
String fallbackResult = "Error processing data";
try {
interp.set("input_data", data);
PyObject result = interp.eval("process_input(input_data)");
return result.toString();
} catch (PyException e) {
if (e.match(Py.ImportError)) {
// Module not available, use Java fallback
return processDataFallback(data);
} else if (e.match(Py.ValueError)) {
// Invalid data, return error message
return "Invalid input: " + e.value;
} else {
// Log error and return fallback
System.err.println("Python processing failed: " + e);
return fallbackResult;
}
}
}
private String processDataFallback(String data) {
// Java implementation as fallback
return "Processed by Java: " + data.toUpperCase();
}
}public class RetryingJythonExecutor {
private PythonInterpreter interp;
public Object executeWithRetry(String primaryCode, String fallbackCode) {
// Try primary approach
try {
return interp.eval(primaryCode);
} catch (PyException e) {
System.out.println("Primary approach failed: " + e.value);
// Try fallback approach
try {
return interp.eval(fallbackCode);
} catch (PyException fallbackError) {
System.err.println("Both approaches failed");
System.err.println("Primary: " + e.value);
System.err.println("Fallback: " + fallbackError.value);
throw fallbackError;
}
}
}
}public class ExceptionAnalyzer {
public static void analyzeException(PyException e) {
System.out.println("=== Exception Analysis ===");
System.out.println("Type: " + e.type);
System.out.println("Value: " + e.value);
System.out.println("Message: " + e.getMessage());
// Java stack trace
System.out.println("\nJava Stack Trace:");
e.printStackTrace();
// Python traceback
if (e.traceback != null) {
System.out.println("\nPython Traceback:");
e.traceback.dumpStack();
}
// Exception cause chain
Throwable cause = e.getCause();
int level = 1;
while (cause != null) {
System.out.println("\nCause Level " + level + ": " + cause.getMessage());
cause = cause.getCause();
level++;
}
System.out.println("=== End Analysis ===");
}
}
// Usage:
try {
interp.exec("complex_operation()");
} catch (PyException e) {
ExceptionAnalyzer.analyzeException(e);
}Install with Tessl CLI
npx tessl i tessl/maven-org-python--jython-standalone