...making Linux just a little more fun!

<-- prev | next -->

A Look At Jython

By Rob Tougher

This article discusses Jython, a software project that aims to provide seamless integration between Java and Python. This article requires a basic understanding of both languages.

Introduction

There are many different programming languages. The Language List, a comprehensive database of computer languages, puts the number at around 2500. Having different languages is advantageous to developers - each language has features that are well-suited to certain classes of problems. For example, when I'm transforming XML, XSLT is my tool of choice (this is a popular method of rendering HTML for dynamic web sites). When coding server-based applications, I prefer languages such as Java, C++ and Python. I think the general advice for programmers is to "use the right tool for the job".

One noticeable drawback in this abundance of languages is the inability (or extreme difficulty) in reusing code written in one language from another language. For example, say you had written a database library in Java, and wanted to reuse that library in Python. You could write a glue layer, using a technology like COM, CORBA, sockets, or SOAP, but that layer would take time to write. It would be nice if this glue layer already existed, ready to be consumed with little or no effort expended.

Enter Jython. The goal of the Jython project is to provide seamless integration between Java and Python. The project contains two main tools:

This article provides a basic introduction to Jython. First I'll describe installation, next I'll talk about the jython interpreter, and I'll finish up with a discussion of the jythonc compiler. I'll use the following naming conventions when referring to the different interpreters, compilers, and projects:

Installation

To use Jython on your system you need two pieces of software: the Java SDK, and the Jython distribution.

You can get Sun's latest Java SDK for Linux (1.4.2) at the main Java site. Sun distributes the SDK as a single binary file that you can download and run on your Linux machine. After the install completes, the remaining step is to create an environment variable named JAVA_HOME, and set its value to the root directory of the Java installation. I set this variable as part of my ~/.bashrc file:

#
# For the 1.4.2 sdk
#

export JAVA_HOME=~/apps/j2sdk1.4.2_01
export PATH=~/apps/j2sdk1.4.2_01/bin:$PATH

Notice that I set the PATH environment variable also - I do this so that I can access the Java command line tools (java, javac, jar, etc) from any directory.

The latest release of Jython (2.1) is distributed from the main Jython site. The Jython project provides a graphical installer written in Java and packaged as a single Java *.class file. When you run the installer you are presented with a graphical setup wizard, which asks you to specify the installation type, agree to the license terms, and specify the target directory for installation. When the install completes, you are ready to use Jython on your machine. It is useful to update your PATH and CLASSPATH variables to point at the newly installed Jython distribution. I do this in my ~/.bashrc file:

#
# For Jython
#

export JYTHON_HOME=~/jython-2.1/
export PATH=$JYTHON_HOME:$PATH
export CLASSPATH=$JYTHON_HOME/jython.jar:$CLASSPATH

To check that your installation succeeded, type "jython" at the command prompt:

prompt$ jython
Jython 2.1 on java1.4.2_01 (JIT: null)
Type "copyright", "credits" or "license" for more information.
>>>

If you see the above, you've successfully installed Jython.

Using The Jython Interpreter

The jython interpreter is a Python interpreter implemented in 100% Java. It allows you to write Python code that accesses Java classes.

The latest stable version of jython, released in December of 2001, implements features of Python 2.1. Python, however, has already reached version 2.3. This means that Python features unique to versions 2.2 and 2.3 are unavailable in the current stable version of jython:

An alpha version of jython, available for download at the Jython site, implements a mixture of Python 2.1 and 2.2. The Jython group characterizes this alpha version as an unstable and experimental release that contains significant known issues. In other words, use the alpha version at your own risk.

Besides lacking recent Python language features, jython is missing some Python modules in its library implementation. On top of that, there is little documentation describing which modules are supported and which are not. If you want to know if a module is supported, the FAQ suggests attempting to import the module in question. If the import fails, you can try to copy over the corresponding *.py module from the CPython implementation. As a last effort you can request help on the public mailing lists.

While the Python support in jython is restricted to version 2.1, the Java support is completely up-to-date. You can use _any_ Java code from inside the jython interpreter. This includes the standard Java 1.4.2 libraries, libraries written by third parties, and your own custom libraries.

For example, you could use Java's Abstract Window Toolkit (AWT). The AWT is a graphical windowing library that provides widgets for creating user interfaces (windows, buttons, text areas, etc). You could write Python code that accessed the AWT, and then run that code using the jython interpreter.

Here's an example of using AWT functionality from within Python:

#
# file: AWTTest.jy
#

#
# Import the AWT classes.
#

from java.awt import Frame
from java.awt import Panel
from java.awt import Button
from java.awt import TextArea
from java.awt.event import ActionListener


#
# Define the TestButtonAction class. TestButtonAction
# inherits from the Java ActionListener interface.
#

class TestButtonAction(ActionListener):

        def actionPerformed(self, e):
                textArea.append("Test Button Clicked!\n")


#
# Create the Frame, Panel, Button,
# TextArea, and TestButtonAction objects.
#

frame = Frame("Hello World")
panel = Panel() 
button = Button("Test Button")
buttonAction = TestButtonAction()
textArea = TextArea()


#
# Put everything together and show
# the window.
#

button.addActionListener(buttonAction)
panel.add(button)
panel.add(textArea)
frame.add(panel)
frame.pack()
frame.show()

You can run this using the jython interpreter:

prompt$ jython AWTTest.jy

Running this code should produce a window similar to the following:

[screenshot]

The example creates a window and adds a Button and a TextArea to it. When you click the button, the text "Test Button Clicked!" is appended to the TextArea's contents. The example displays a few key features of Jython:

Using The Jythonc Compiler

The second tool that the Jython project provides is jythonc. jythonc compiles Python source code into Java bytecode. This Java bytecode can be executed using a standard Java Virtual Machine.

(Java bytecode is the intermediate language that the Java Virtual Machine executes. When you compile a Java source file using javac, the compilation output is a file with a *.class extension. This file contains Java bytecode, which you can execute using the Java Virtual Machine. For more information about Java bytecode and the JVM, check out The Java Virtual Machine Specification )

jythonc suffers from the same feature lag as the jython interpreter - the latest jythonc release implements features from Python 2.1. Furthermore, the alpha version of Jython contains a jythonc compiler that is basically unchanged since the last release. It looks like jythonc will be stuck at version 2.1 for a while.

When compiling a Python class with jythonc, you need to provide extra information about each publically accessible method in your class. This information includes the return type, arguments, argument types, throws clause, and access control declaration (private, public, or protected). You can provide this information in one of two ways:

For example, you could write a Java Servlet in Python (servlets are Java classes that run inside servlet containers, like Tomcat and Jetty, and respond to web page requests). You could create a Python class that derives from HttpServletRequest, compile that class into bytecode using the jythonc compiler, and run that bytecode inside of a servlet container.

The following is a simple servlet written in Python:

#
# file HelloWorldFromJython.py
#

import os
from javax.servlet.http import HttpServlet


class HelloWorldFromJython(HttpServlet):

        def service(self, request, response):

                response.setContentType("text/html")
                out = response.getOutputStream()
                print >>out, """<html>
                                <head>
                                        <title>Hello World Servlet</title>
                                </head>
                                <body>
                                        <p>Hello World From Jython!</p>
                                        <p>os.getcwd() == """ + str(os.getcwd()) + """</p>
                                </body>
                                </html>"""

You can run this example using Tomcat. Tomcat installation is pretty straightforward - it only requires downloading the distribution and extracting it to your hard drive. You should create an environment variable named TOMCAT_HOME and set its value to the Tomcat root directory:

#
# For Tomcat.
#

export TOMCAT_HOME=~/apps/jakarta-tomcat-4.1.27/

The next step is to compile the Python servlet with the jythonc compiler (note that the CLASSPATH environment variable needs to be updated to include the servlet.jar archive):

prompt$ export CLASSPATH=$TOMCAT_HOME/common/lib/servlet.jar:$CLASSPATH
prompt$ jythonc --deep HelloWorldFromJython.py

processing HelloWorldFromJython
processing javaos
processing string
processing UserDict
processing copy
processing repr
processing javapath
processing re
processing sre
processing sre_constants
processing sre_compile
processing copy_reg
processing sre_parse

Required packages:
  java.lang
  org.python.core
  java.io
  javax.servlet.http

Creating adapters:

Creating .java files:
  sre_constants module
  javaos module
  sre module
  javapath module
  re module
  string module
  sre_compile module
  copy_reg module
  HelloWorldFromJython module
    HelloWorldFromJython extends javax.servlet.http.HttpServlet
  UserDict module
  sre_parse module
  repr module
  copy module

Compiling .java to .class...

[snip]

The jythonc compiler creates a directory named "jpywork" in your current directory. This directory contains the *.class file output of the jythonc compilation, along with supporting files.

The next step is to deploy the binary *.class files to the Tomcat server's webapps directory. Normally you would create a new web application for your servlets, but for this example you can use the existing "examples" web application that ships with Tomcat. Create a new directory inside of that web application and copy the class files to it:

prompt$ mkdir $TOMCAT_HOME/webapps/examples/WEB-INF/classes/HelloWorldFromJython
prompt$ cp jpywork/*.class $TOMCAT_HOME/webapps/examples/WEB-INF/classes/HelloFromJython/

Next add the jython.jar archive to the webapp's lib directory (if the directory doesn't exist, create it):

prompt$ mkdir $TOMCAT_HOME/webapps/examples/WEB-INF/lib
prompt$ cp $JYTHON_HOME/jython.jar $TOMCAT_HOME/webapps/examples/WEB-INF/lib/

Now that the Python servlet has been compiled and deployed to the Tomcat server, and the jython.jar archive has been included in the lib directory, you can run the Tomcat server:

prompt$ $TOMCAT_HOME/bin/startup.sh

Using CATALINA_BASE:   /home/robt/apps/jakarta-tomcat-4.1.27
Using CATALINA_HOME:   /home/robt/apps/jakarta-tomcat-4.1.27
Using CATALINA_TMPDIR: /home/robt/apps/jakarta-tomcat-4.1.27/temp
Using JAVA_HOME:       /home/robt/apps/j2sdk1.4.2_01

You should be able to access your Python servlet using the following URL:

The servlet will produce output similar to the following:

prompt$ wget https://yourmachine:8080/examples/servlet/HelloWorldFromJython/HelloW
orldFromJython

prompt$ cat HelloWorldFromJython

<html>
	<head>
		<title>Hello World Servlet</title>
	</head>
	<body>
		<p>Hello World From Jython!</p>
		<p>os.getcwd() == /home/robt/apps/jakarta-tomcat-4.1.27/bin</p>
	</body>
</html>

Conclusion

This article served as an introduction to the Jython project. For more information about the subjects presented in this article, check out the following links:

 


[BIO PEN] Rob is a software developer in the New York City area.

Copyright © 2003, Rob Tougher. Released under the Open Publication license unless otherwise noted in the body of the article. Linux Gazette is not produced, sponsored, or endorsed by its prior host, SSC, Inc.

Published in Issue 97 of Linux Gazette, December 2003

<-- prev | next -->
Tux