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 optionsmodules

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 --jarjarfile, 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 --addpackagespackages 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
--beanjarfile, which
also includes a bean manifest in the .jar file
as needed for Python-coded JavaBeans components.

Another useful jythonc option is
--packagepackage,
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:

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:

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.

25.3.3.1 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 --jarsomejar.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.

25.3.3.2 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.