25.3 Compiling Python into Java

Jython comes with the jythonc compiler. You can feed jythonc your .py source files, and jythonc compiles them into normal JVM bytecode and packages them into .class and .jar files. Since jythonc generates static, classic bytecode, it cannot quite cope with the whole range of dynamic possibilities that Python allows. For example, jythonc cannot successfully compile Python classes that determine their base classes dynamically at runtime, as the normal Python interpreters allow. However, except for such extreme examples of dynamically changeable class structures, jythonc does support compilation of essentially the whole Python language into Java bytecode.

25.3.1 The jythonc command

jythonc resides in the Tools/jythonc directory of your Jython installation. You invoke it from a shell (console) command line with the syntax:

jythonc options modules

options are zero or more option flags starting with --. modules are zero or more names of Python source files to compile, either as Python-style names of modules residing on Python's sys.path, or as relative or absolute paths to Python source files. Include the .py extension in each path to a source file, but not in a module name.

More often than not, you will specify the jythonc option --jar jarfile, to build a .jar file of compiled bytecode rather than separate .class files. Most other options deal with what to put in the .jar file. You can choose to make the file self-sufficient (for browsers and other Java runtime environments that do not support using multiple .jar files) at the expense of making the file larger. Option --all ensures all Jython core classes are copied into the .jar file, while --core tries to be more conservative, copying as few core classes as feasible. Option --addpackages packages lets you list (in packages, a comma-separated list) those external Java packages whose classes are copied into the .jar file if any of the Python classes jythonc is compiling depends on them. An important alternative to --jar is --bean jarfile, which also includes a bean manifest in the .jar file as needed for Python-coded JavaBeans components.

Another useful jythonc option is --package package, which instructs Jython to place all the new Java classes it's creating in the given package (and any subpackages of package needed to reflect the Python-side package structure).

25.3.2 Adding Java-Visible Methods

The Java classes that jythonc creates normally extend existing classes from Java libraries and/or implement existing interfaces. Other Java-coded applications and frameworks instantiate the jythonc-created classes via constructor overloads, which have the same signatures as the constructors of their Java superclasses. The Python-side _ _init_ _ executes after the superclass is initialized, and with the same arguments (therefore, don't _ _init_ _ a Java superclass in the _ _init_ _ of a Python class meant to be compiled by jythonc). Afterward, Java code can access the functionality of instances of Python-coded classes by calling instance methods defined in known interfaces or superclasses and overridden by Python code.

Python code can never supply Java-visible static methods or attributes, only instance methods. By default, each Python class supplies only the instance methods it inherits from the Java class it extends or the Java interfaces it implements. However, Python code can also supply other Java-visible instance methods via the @sig directive.

To expose a method of your Python class to Java when jythonc compiles the class, code the method's docstring as @sig followed by a Java method signature. For example:

class APythonClass:
    def __init_  _(self, greeting="Hello, %s!"):
        "@sig public APythonClass(String greeting)"
        self.greeting = greeting
    def hello(self, name):
        "@sig public String hello(String name)"
        return self.greeting % name

To expose a constructor, use the @sig signature for the class, as shown in the previous example. All names of classes in @sig signatures must be fully qualified, except for names coming from java.lang and names supplied by the Python-coded module being compiled. When a Python method with a @sig has optional arguments, jythonc generates Java-visible overloads of the method with each legal signature, and deals with supplying the default argument values where needed. An _ _init_ _ constructor with a @sig, for a Python class that extends a Java class, initializes the superclass using the superclass's empty constructor.

Since a Python class cannot expose data attributes directly to Java, you may need to code accessors with the usual JavaBeans convention and expose them via the @sig mechanism. For example, instances of APythonClass in the above example do not allow Java code to directly access or change the greeting attribute. When such functionality is needed, you can supply it in a subclass as follows:

class APythonBean(APythonClass):
    def getGreeting(self):
        "@sig public String getGreeting(  )"
        return self.greeting
    def setGreeting(self, greeting):
        "@sig public void setGreeting(String greeting)"
        self.greeting = greeting

25.3.3 Python Applets and Servlets

Two typical examples of using Jython within existing Java frameworks are applets and servlets. Applets are typical examples of jythonc use (with specific caveats), while servlets are specifically supported by a Jython-supplied utility. Python applets

A Jython applet class must import java.applet.Applet and extend it, typically overriding method paint and others. You compile the applet into a .jar file by calling jythonc with options --jar somejar.jar and either --core or --all. Normally, Jython is installed in a modern Java 2 environment, which is okay for most uses. It is fine for applets, as long as the applets run only in browsers that support Java 2, typically with a Sun-supplied browser plug-in. However, if you need to support browsers that are limited to Java 1.1, you must ensure that the JDK you use is Release 1.1, and that you compile your applet with Jython under a JDK 1.1 environment. It's possible to share a single Jython installation between different JDKs, such as 1.1 and 1.4. However, I suggest you perform separate installations of Jython, one under each JDK you need to support, in separate directories, in order to minimize the risk of confusion and accidents. Python servlets

You can use jythonc to build and deploy servlets. However, Jython also supports an alternative that lets you deploy Python-coded servlets as source .py files. Use the servlet class org.python.util.PyServlet, supplied with Jython, and a servlet mapping of all *.py URLs to PyServlet. Each servlet .py file must reside in the web-app top-level directory, and must expose an object callable without arguments (normally a class) with the same name as the file. PyServlet uses that callable as a factory for instances of the servlet, and calls methods on the instance according to the Java Servlet API. Your servlet instance, in turn, accesses Servlet API objects such as the request and response objects, passed as method arguments, and those objects' attributes and methods such as response.outputStream and request.getSession. PyServlet provides an excellent, fast-turnaround way to experiment with servlets and rapidly deploy them.

    Part III: Python Library and Extension Modules