Introduction to Jython

January 9th, 2006

  • Ian Maurer: http://www.itmaurer.com/
  • Xteric Technology Group: http://www.xteric.com/
  • Cleveland Area Python Interest Group: http://www.clepy.org/

What is Jython?

Jython is an implementation of the high-level, dynamic, object-oriented language Python written in 100% Pure Java, and seamlessly integrated with the Java platform. It thus allows you to run Python on any Java platform.
Jython is an excellent dynamic counterpart to Java's static language. Jython provides a developer a very high level method for prototyping, scripting, and testing Java components.
  • Jython: http://www.jython.org

Why Jython?

While there are numerous language implementations on the JVM, the following separate Jython from the rest:
  • Dynamic compilation to Java bytecodes - highest possible performance without sacrificing interactivity.
  • Ability to extend existing Java classes in Jython
  • Optional static compilation - for creation of applets, servlets, etc.
  • Bean Properties - make use of Java packages much easier.
  • Python Language - combines remarkable power with very clear syntax. It also supports a full object-oriented programming model which makes it a natural fit for Java's OO design.
  • Original Wiki Document: http://wiki.python.org/jython/WhyJython

What does Jython do Well?

  • Java Library Investigation with the Jython Interpreter
  • Protyping Java Components and Libraries
  • Glue together libraries already written in Java
  • Embedded scripting language
  • Original Wiki Document: http://wiki.python.org/jython/WhyJython

Beginning of Jython

Jim Hugunin began Jython during a one-week experiment back in 1997 after discovering:
  • That the static Java and dynamic Python languages complemented each other well, while still being similar enough to work together.
  • Python programs could be translated into Java bytecode without significant performance loss.
  • The java.reflect package made it possible to load and use arbitrary Java libraries from Python without having to write any glue code
Jim handed off the project in 1999 and is now working for Microsoft on a version of Python for the .NET and Mono platforms called IronPython.
  • Story of Python: http://hugunin.net/story_of_jython.html
  • IronPython: http://www.ironpython.com/

CPython

In the strict sense, "Python" is just a programming language. A set of keywords and syntax rules that is defined by the Python Reference Manual. A programming language that has gone through several revisions over the years.
Most people, most of the time, also refer to the implementation of the Python interpreter written in the C language as "Python". Its also the name of the program that runs the C interpreter.
However, when people speak about the "Jython" interpreter, then they usually use the name "CPython" to refer back to the original C implementation.
  • Python Reference: http://www.python.org/doc/versions.html
  • Python Documentation by Version: http://www.python.org/doc/versions.html

Differences between CPython and Jython

Some examples:
  • __del__ is not reliable because the Java garbage collector is used
  • Java only has Unicode strings
  • Cannot mix Python and Java classes in multiple inheritance
  • Java instances cannot have dynamic attributes
  • Boolean type difficult to address:
    public void do(int i);
    public void do(boolean b);
  • Differences between CPython and Jython: http://www.jython.org/docs/differences.html
  • Differences (Brian Zimmer's Presentation): http://www.ziclix.com/jython/chipy20050113/slide-05.html

Peformance Differences

The startup time of the JVM makes Jython's startup time 10-20x slower than CPython's startup time. This makes Jython a very poor choice for any situation where numerous processes need to be started and finished quickly, such as straight CGI programming.
Jython does benefit from the advantages that Java itself has over CPython. For instance, Java supports multiple threads while CPython does not, due to the Global Interpreter Lock.
  • Startup Time: http://www.ziclix.com/jython/chipy20050113/slide-27.html
  • Global Interpreter Lock: http://docs.python.org/api/threads.html

Current Status (January 9th, 2006)

Development of Jython has always lagged the CPython version with regards to new functionality and changes to the language. But, while it lags in features to it's C counterpart, it still is a very reliable and stable programming environment.
The current stable and recommended version of Jython is 2.1. There is also an alpha release of Jython 2.2.
The latest builds can always be found here:
  • SourceForge Jython Download: http://sourceforge.net/project/showfiles.php?group_id=12867&release_id=342904

Installing Jython

Jython is distributed in a self-extracting .class file. To install it, simply run it in the java interpreter from the command line:
    java jython-21
Notice that you do not include the .class extension. If you run into problems check the following links:
  • Jython.org Installation Guide: http://www.jython.org/install.html
  • Jython FAQ: Installation and Setup: http://wiki.python.org/jython/JythonFaq/InstallingJython

Jython Registry

Jython aquires it's namespace for variables (such as python.path and python.security.respectJavaAccessibility) from the following sources (in ascending priority):
  • Java system (JVM) properties
  • System-wide jython "registry" file
  • User-specific jython "registry" file
  • Jython command line options
For more information see this link:
  • Jython.org: The Jython Registry: http://www.jython.org/docs/registry.html

Jython Interpreter

The Jython Interpreter is very useful for testing out Java APIs.

    C:\> jython
    Jython 2.1 on java1.5.0_04 (JIT: null)
    Type "copyright", "credits" or "license" for more information.
    >>> import java
    >>> m = java.util.HashMap()
    >>> m.put("hello", "world")
    >>> m.get("hello")
    world

Jylluminate Module

The Jylluminate module makes interrogating Java objects from Jython easier.
    >>> import java, jylluminate
    >>> v = java.util.Vector()
    >>> print jylluminate.methods(v)

    methods implemented by the java.util.Vector class
        addElement
        capacity
        copyInto
        elementAt
        elements
        ensureCapacity
        firstElement
        insertElementAt
        lastElement
        removeAllElements
        removeElement
        removeElementAt
        setElementAt
        setSize
        trimToSize
  • Jylluminate module: http://home.earthlink.net/~kip.lehman/jython/jylluminate.py

Jylluminate Module (Continued)

    >>> print jylluminate.lineage(java.util.Vector())
    
    class: java.util.Vector
    
    superclass hierarchy (excluding Object):
        java.util.AbstractList
            java.util.List                   (interface)
                java.util.RandomAccess       (interface)
                    java.lang.Cloneable      (interface)
                        java.io.Serializable (interface)
                            java.util.Vector
    
    methods defined in interfaces/implemented in superclasses (minus Object):
        java.util.AbstractList
            iterator
            listIterator
            listIterator
  • Jylluminate module: http://home.earthlink.net/~kip.lehman/jython/jylluminate.py

Jylluminate Module (Continued)

        java.util.List    (interface)
            add
            addAll
            get
            indexOf
            lastIndexOf
            listIterator
            remove
            set
            subList
            toArray
  • Jylluminate module: http://home.earthlink.net/~kip.lehman/jython/jylluminate.py

JavaBean Properties

Setting a property using a Java-style method call:
  b = awt.Button()
  b.setEnabled(0)
Using a property as an attribute:
  b = awt.Button()
  b.enabled = 0
Setting a property using keyword argument at instantiation:
  b = awt.Button(enabled=0)
  • Jyton.org Properties Page: http://www.jython.org/docs/properties.html

Event Listener

Java-style (Class-based) Event Listener:
  class action(awt.event.ActionListener):
      def actionPerformed(self,event):
          java.lang.System.exit(0)
  
  button = awt.Button("Close Me!")
  button.addActionListener(action())
Python-style (Function-based) Event Listener:
  def exit(event):
      java.lang.System.exit(0)
  
  button = awt.Button("Close Me!", actionPerformed=exit)
  • Jyton.org Properties Page: http://www.jython.org/docs/properties.html

Java Arrays in Jython

The "jarray" module provides 2 methods for creating Java arrays:
    array(sequence, type)
    zeros(length, type)
The type argument is either a java class or a 1 letter code for a java primitive type:
    z: boolean    c: char
    b: byte       h: short
    i: int        l: long
    f: float      d: double

Java Arrays in Jython (Examples)

The below example shows how to create an empty byte array for use with a InputStream read:
    buffer = jarray.zeros(bufferSize, "b") 
    readsize = stream.read(buf)
The 2nd example shows to make an array of Integers from 0 to 4 and an array of Doubles from 0.0 to 4.0:
    # array([0, 1, 2, 3, 4], java.lang.Integer)
    jarray.array(range(5), java.lang.Integer)
    
    # array([0.0, 1.0, 2.0, 3.0, 4.0], java.lang.Double)
    jarray.array(range(5), java.lang.Double)

Database Connectivity (JDBC)

When connecting to a JDBC datasource, you can use the Java classes directly. However, for those wishing to use a Python DB API, then you can use the zxJDBC library that comes with Jython.
The following pages show how to print out a row of data in Java, Jython using the Java APIs, and Jython using the zxJDBC library. For more information about JDBC, please check these links:
  • Database Connectivity in Jython: http://www.jython.org/docs/zxjdbc.html
  • Brian Zimmer's JDBC Examples: http://www.ziclix.com/jython/chipy20050113/slide-19.html

JDBC (Java Example)

import java.sql.*;
import java.util.*;

public class JDBCExample {
  public static void main(String[] args) throws Exception {
    Class.forName("org.postgresql.Driver");
    Connection db = DriverManager.getConnection("jdbc:postgresql://localhost/racing/", "bzimmer", null);
    Statement c = db.createStatement();
    ResultSet rs = c.executeQuery("select * from bz");
    
    while (rs.next()) {
      List row = new ArrayList();
      ResultSetMetaData meta = rs.getMetaData();
      for(int i=0;i<meta.getColumnCount();i++) {
        int col = i+1;
        int datatype = meta.getColumnType(col);
        if (datatype == Types.INTEGER) {
          row.add(new Integer(rs.getInt(col)));
        } else if (datatype == Types.FLOAT) {
          row.add(new Float(rs.getFloat(col)));
        } else {
          row.add(rs.getString(col));
        }
      }
      System.out.println(row);
    }
    rs.close();
    c.close();
    db.close();
  }
}

JDBC (Jython Example)

from java.sql import *
from java.lang import *

Class.forName("org.postgresql.Driver")

db = DriverManager.getConnection("jdbc:postgresql://localhost/racing/", "bzimmer", None)
c = db.createStatement()
rs = c.executeQuery("select * from bz")

_types = {Types.INTEGER:rs.getInt, Types.FLOAT:rs.getFloat}

while rs.next():
  row = []
  meta = rs.getMetaData()
  for i in range(meta.getColumnCount()):
    col = i + 1
    datatype = meta.getColumnType(col)
    v = _types.get(datatype, rs.getString)(col)
    row.append(v)
  print tuple(row)
rs.close()
c.close()
db.close()

JDBC (zxJDBC Example)

from com.ziclix.python.sql import zxJDBC

db = zxJDBC.connect("jdbc:postgresql://localhost/racing/", "bzimmer", None, "org.postgresql.Driver")
c = db.cursor()
c.execute("select * from bz")
for row in c:
  print row
c.close()
db.close()

Jython Compiler

In order to build a real Java class from a Python class, you can use the "jythonc" script. Some tips:
  • Be sure to set python.jythonc.compiler registry setting
  • If you are not overriding an existing method, then you need to clue in the compiler as to the signature of your method:
            def setExpression(self, e):
                "@sig public void setExpression(java.lang.String e)"
  • Use the --jar and --core options when building applets.
For more information about the jythonc options:
  • Compiling Python Source to Real Java Classes: http://www.jython.org/docs/jythonc.html

Compiling Jython Example

Foo.py

    import java
    class Foo(java.util.Date):
        def __init__(self):
            self.count = 0
        def bar(self, incr=1):
            """@sig void bar(int incr)"""
            self.count += incr
            return self.count
        def toString(self):
            cnt = self.bar()
            return "Foo[" + java.util.Date.toString(self) + " " + `cnt` + "]"

Compiling Jython Example (Continued)

Compiling Jython Class

  C:\foo>jythonc Foo.py
  processing Foo
  
  Required packages:
    java.util
  
  Creating adapters:
  
  Creating .java files:
    Foo module
      Foo extends java.util.Date
  
  Compiling .java to .class...
  Compiling with args: ['javac', '-classpath', 'C:\\Jython21\\jython.jar;...',
  '.\\jpywork\\Foo.java']

Compiling Jython Example (Continued)

FooTest.java

  import Foo;
  public class FooTest {
     public static void main(String[] args) {
         Foo foo = new Foo();
         System.out.println(foo);
         foo.bar();
         foo.bar(43);
         System.out.println(foo);
     }
  }

Compiling Jython Example (Continued)

Running FooTest

    C:\foo>java -cp ".;jpywork;C:\Jython21\jython.jar" FooTest
    Foo[Mon Jan 09 19:00:00 EST 2006 1]
    Foo[Mon Jan 09 19:00:00 EST 2006 46]
  

Creating a JAR

The 'jythonc' script can be used to create Java Archive files (JARs) through it's options. Below is an example for creating the Applet demos on the Jython.org website:

    jythonc --core --deep --jar appletdemo.jar *.py

Applet Demo

    from java import awt, applet
    
    class ButtonDemo(applet.Applet):
        def init(self):
            self.b1 = awt.Button('Disable middle button', actionPerformed=self.disable)
            self.b2 = awt.Button('Middle button')
            self.b3 = awt.Button('Enable middle button', enabled=0, actionPerformed=self.enable)
    
            self.add(self.b1)
            self.add(self.b2)
            self.add(self.b3)
    
        def enable(self, event):
            self.b1.enabled = self.b2.enabled = 1
            self.b3.enabled = 0
    
        def disable(self, event):
            self.b1.enabled = self.b2.enabled = 0
            self.b3.enabled = 1

See Demo

IDE Support

To go along with the Python specific editors and IDEs, there are 3 main projects that focus on Jython and (in the case of Coyote) other JVM scripting languages:
  • NetBeans IDE Coyote Project: https://coyote.dev.java.net/

More Information

For more information, check out these links: