25.2 Embedding Jython in Java
Your Java-coded application can embed the Jython interpreter in order to use Jython for scripting. jython.jar must be in your Java CLASSPATH. Your Java code must import org.python.core.* and org.python.util.* in order to access Jython's classes. To initialize Jython's state and instantiate an interpreter, use the Java statements:
PySystemState.initialize( ); PythonInterpreter interp = new PythonInterpreter( );
Jython also supplies several advanced overloads of this method and constructor in order to let you determine in detail how PySystemState is set up, and to control the system state and global scope for each interpreter instance. However, in typical, simple cases, the previous Java code is all your application needs.
25.2.1 The PythonInterpreter Class
Once you have an instance interp of class PythonInterpreter, you can call method interp.eval to have the interpreter evaluate a Python expression held in a Java string. You can also call any of several overloads of interp.exec and interp.execfile to have the interpreter execute Python statements held in a Java string, a precompiled Jython code object, a file, or a Java InputStream.
The Python code you execute can import your Java classes in order to access your application's functionality. Your Java code can set attributes in the interpreter namespace by calling overloads of interp.set, and get attributes from the interpreter namespace by calling overloads of interp.get. The methods' overloads give you a choice. You can work with native Java data and let Jython perform type conversions, or you can work directly with PyObject, the base class of all Python objects, covered later in this chapter. The most frequently used methods and overloads of a PythonInterpreter instance interp are the following.
Evaluates, in interp's namespace, the Python expression held in Java string s, and returns the PyObject that is the expression's result.
Executes, in interp's namespace, the Python statements held in Java string s or in compiled PyObject code (produced by function _ _builtin_ _.compile of package org.python.core, covered later in this chapter).
Executes, in interp's namespace, the Python statements read from the stream s or from the file named name. When you pass both s and name, execfile reads the statements from s, and uses name as the filename in error messages.
Fetches the value of the attribute named name from interp's namespace. The overload with two arguments also converts the value to the specified javaclass, throwing a Java PyException exception that wraps a Python TypeError if the conversion is unfeasible. Either overload raises a NullPointerException if name is unbound. Typical use of the two-argument form might be a Java statement such as:
String s = (String)interp.get("attname", String.class);
Binds the attribute named name in interp's namespace to value. The second overload also converts the value to a PyObject.
The org.python.core package supplies a class _ _builtin_ _ whose static methods let your Java code access the functionality of Python built-in functions. The compile method, in particular, is quite similar to Python built-in function compile, covered in Chapter 8 and Chapter 13. Your Java code can call compile with three String arguments (a string of source code, a filename to use in error messages, and a kind that is normally "exec"), and compile returns a PyObject instance p that is a precompiled Python bytecode object. You can repeatedly call interp.exec(p) to execute the Python statements in p without the overhead of compiling the Python source for each execution. The advantages are the same as covered in Chapter 13.
25.2.2 The PyObject Class
Seen from Java, all Jython objects are instances of classes that extend PyObject. Class PyObject supplies methods named like Python objects' special methods, such as _ _len_ _, _ _str_ _, and so on. Concrete subclasses of PyObject override some special methods to supply meaningful implementations. For example, _ _len_ _ makes sense for Python sequences and mappings, but not for numbers; _ _add_ _ makes sense for numbers and sequences, but not for mappings. When your Java code calls a special method on a PyObject instance that does not in fact supply the method, the call raises a Java PyException exception wrapping a Python AttributeError.
PyObject methods that set, get, and delete attributes exist in two overloads, as the attribute name can be a PyString or a Java String. PyObject methods that set, get, and delete items exist in three overloads, as the key or index can be a PyObject, a Java String, or an int. The Java String instances that you use as attribute names or item keys must be Java interned strings (i.e., either string literals or the result of calling s.intern( ) on any Java String instance s). In addition to the usual Python special methods _ _getattr_ _ and _ _getitem_ _, class PyObject also provides similar methods _ _findattr_ _ and _ _finditem_ _, the difference being that, when the attribute or item is not found, the _ _find methods return a Java null, while the _ _get methods raise exceptions.
Every PyObject instance p has a method _ _tojava_ _ that takes a single argument, a Java Class c, and returns an Object that is the value of p converted to c (or raises an exception if the conversion is unfeasible). Typical use might be a Java statement such as:
String s = (String)mypyobj._ _tojava_ _(String.class);
Method _ _call_ _ of PyObject has several convenience overloads, but the semantics of all the overloads come down to _ _call_ _'s fundamental form:
PyObject p._ _call_ _(PyObject args, String keywords);
When array keywords has length L, array args must have length N greater than or equal to L, and the last L items of args are taken as named actual arguments, the names being the corresponding items in keywords. When args has length N greater than L, args's first N-L items are taken as positional actual arguments. The equivalent Python code is therefore similar to:
def docall(p, args, keywords): assert len(args) >= len(keywords) deltalen = len(args) - len(keywords) return p(*args[:deltalen], ** dict(zip(keywords, args[deltalen:])))
Jython supplies concrete subclasses of PyObject that represent all built-in Python types. You can sometimes usefully instantiate a concrete subclass in order to create a PyObject for further use. For example, class PyList extends PyObject, implements a Python list, and has constructors that take an array or a java.util.Vector of PyObject instances, as well as an empty constructor that builds the empty list .
25.2.3 The Py Class
The Py class supplies several utility class attributes and static methods. Py.None is Python's None. Method Py.java2py takes a single Java Object argument and returns the corresponding PyObject. Methods Py.py2type, for all values of type that name a Java primitive type (boolean, byte, long, short, etc.), take a single PyObject argument and return the corresponding value of the given primitive Java type.