|
|
|
Contents: |
|
|
|
Related content: |
|
|
|
Subscriptions: |
|
|
| Learn how the Java implementation of Python can aid your
development efforts
Uche
Ogbuji (mailto:uche.ogbuji@fourthought.com?cc=&subject=Charming
Jython) Principal Consultant, Fourthought, Inc. 6 May 2003
Jython, the 100% Pure Java implementation
of the Python programming language, combines the advantages of Python
and the Java virtual machine and library and serves as a handy
complement to the Java platform. In this article, software consultant
and frequent developerWorks contributor Uche Ogbuji introduces
Jython 2.1 to Java developers by contrasting and comparing the way
Python and the Java language create classes and how they use the
interpreter. Uche illustrates the differences by providing samples of
Java library access, as well as the Jython interpreter shell and code
files.
Jython, originally known as JPython, is an all-Java application
that allows developers to use the syntax and most of the features of the
Python programming language. Jython is interesting to Java programmers for
several reasons:
- Jython's version of the Python interpreter shell allows convenient
experimentation and exploration of ideas and APIs without having to go
through the usual Java compile/run cycle.
- Python is dynamic and generic by design, so you don't have to add
these features by using complex libraries (such as those for Java
reflection and introspection). This makes some sorts of development
easier and is especially useful in automated testing frameworks.
- Many developers like Python's syntax and the feel of the language;
they find it a much more productive way to develop and maintain Java
applications.
In this article I will introduce Jython 2.1, the most recent release,
by offering some examples of accessing Java libraries, using the Jython
interpreter shell, and showcasing Jython code files. You don't need to
know Python to follow along, although you will have to learn the language
if you plan to go much further with Jython than the basic examples in this
article.
The environment I use is Red Hat 8.0 (2.4.18 kernel) and J2SE 1.4.0. On
the Jython site (see Resources),
take a look at the Jython platform-specific notes for more information on
platform and Java environment choices for Jython users.
Note: Both the Jython and Java languages operate on the Java
runtime.
Getting started with
Jython Jython is distributed as a single Java class file
containing the installer. Just download jython-21.class and
place the file somewhere in the CLASSPATH , then run
java jython-21 . Select the components you would like to
install (in the examples, I chose all the defaults), accept the license
(which is the open source BeOpen/CNRI license), and specify the
installation directory -- the installer will take care of the rest.
If you run into problems with the installation, see the installation
information page on the Jython Web site. For UNIX platforms, you may want
to add the chosen Jython installation path to your PATH
environment variable. You can now just type "jython" to run the
interactive shell: Listing 1. Running the Jython
shell
$ jython
Jython 2.1 on java1.4.0_01 (JIT: null)
Type "copyright", "credits" or "license" for more information.
>>>
|
The >>> prompt allows you to enter commands and
get immediate results. In Java programming, every program must define at
least one class. Listing 2 illustrates a complete Java program for writing
a message to the screen: Listing 2. A complete Java
program
class App
{
public static void main(String args[])
{
System.out.println("I don't like spam!");
}
}
|
JPython reduces these lines to: Listing 3. Jython
reducing Java code overhead
>>> print "I don't like spam!"
I don't like spam!
>>>
|
The print keyword is one of the key tools, especially in
the interactive shell where it immediately prints its arguments and then
returns you to the shell prompt. Not only is there less code to type and
debug, but you get the results right away, without having to go through a
compile/run cycle. You can print multiple values at once, and use simple
expressions just as easily, as shown here: Listing 4.
Print is a key Jython tool
>>> print "one plus one is", 1+1
one plus one is 2
>>>
|
Jython expressions are similar to Java expressions. The result of
1+1 is an integer that is coerced to a string by
print and concatenated to the initial string as specified by
the comma delimiter.
You don't even need much apparatus to access standard Java libraries
using Jython. The following example accesses
java.util.Random : Listing 5. Accessing
standard Java libraries via Jython
>>> from java.util import Random
>>> rng = Random()
>>> i = rng.nextBoolean()
>>> print i
1
>>>
|
Jython's import keyword is similar to the Java language
version in that it makes the contents of one module available in another,
but there are some syntax and behavior differences.
The example in Listing 5 above uses the related from
keyword to narrow down which symbols are imported from
java.util . The next line shows the creation of an instance of
the Random class. No new keyword is needed, as
you can see.
There is also no type declaration needed for the variable that holds
the new instance. This highlights an important simplification in Jython
and one benefit of its dynamic nature -- it reduces much of the need to
worry about data typing.
The next line in Listing 5 demonstrates method invocation, which is
just the same as in the Java language except for the lack of type
declaration for the result. nextBoolean() in Java code is a
boolean. Jython 2.1 does not have a boolean type (although this may soon
change; Python 2.3 adds a boolean type), so it substitutes an integer of
value 0 or 1. Similarly, to invoke a Java method that
expects a boolean value, you pass in an integer value meeting these
constraints.
You can also use the import keyword in such a way that you
fully qualify the names of all symbols imported, as shown in Listing
6: Listing 6. Import fully qualifies all imported
symbol names
>>> import java.util.Random
>>> rng = java.util.Random()
>>> print rng.nextFloat()
0.9567907452583313
>>>
|
Jython's floating-point values are just the same as in the Java
language.
Writing code directly in the
source The interpreter is handy for quick checking and
prodding, but you don't have to do all your work there -- Jython also
allows you to write code in source files and then run the code (though
with Jython, the compilation step is optional). As an example, the
following listing is a stand-alone Jython program: Listing 7. Sample Jython program that simulates a coin
toss (save in file named listing7.py)
from java.util import Random
rng = Random()
#This is a comment in Jython
print "Flipping a coin..."
if rng.nextBoolean():
print "Came up heads"
else:
print "Came up tails"
|
Let's explain the code before we explain how to run it. This example
introduces if statements in Jython, one of the first things
some people remark about in Jython (as well as its antecedent Python).
There is no character delimiter to mark the block executed when the
condition in the if statement is true (conditions in Jython
do not require enclosing parentheses, as they do in Java programming). The
code is merely indented to a greater degree than the surrounding code.
Blocks of code in Jython are always marked with indentation rather
than, say, curly braces. Statements that introduce code bocks, such as
if , end in colons. This feature of Jython means that you have
to be careful when you write code because the way you indent the code can
actually change the meaning. For example, Listing 8a results in a print
out of only the number 3 because the two statements above it are
part of an if block whose condition is never true: Listing 8a. Indentation: Prints only "3"
if 0:
print "1"
print "2"
print "3"
|
If I merely change the indentation of one of the lines, then the
numbers 2 and 3 are printed: Listing
8b. Indentation: Prints "2" and "3"
if 0:
print "1"
print "2"
print "3"
|
The indentation also has to be consistent, it has to be associated with
statements that organize code into blocks, and usually it also has to
control the flow of code. For example: Listing 8c.
Indentation: A syntax error
print "1"
print "2"
print "3"
|
This would simply result in a syntax error because there is no
controlling statement that requires a block to be separated from the rest
of the code.
The use of indentation to mark code blocks is one of the more
controversial features of Python and Jython, but I believe it is often an
exaggerated issue. After all, it shouldn't matter if you follow good
coding standards in indentation. If good coding indentation is followed,
the fact that a machine enforces this rather than a peer reviewer
shouldn't matter.
Furthermore, I know of no developer who notices this restriction after
a few hours of using the language. It becomes second nature to indent
properly. Certainly this link between indentation and syntax can cause
errors that you may have not encountered before, but the lack of explicit
delimiters also eliminates some errors that are common in languages that
use them.
You can run the file in Listing
7 (listing7.py) without having to compile it just by invoking the
filename as an argument to the jython command, as shown
below: Listing 9. Running "coin toss" without
compilation
$ jython listing7.py
Flipping a coin...
Came up tails
$
|
In the previous example, $ is just the UNIX shell prompt,
much like the C:\> on a Windows system. You can also
compile modules into Java bytecode (.class ) files using the
jpythonc command, which allows you to use the
java or jre command to run it directly. There
are some restrictions on the Jython modules compiled in this way, but that
issue is outside the scope of this article.
Building global
functions You can create global functions with ease in
Jython, even though the Java language does not support global functions.
You can also define global variables (usually to set up constants without
having to make a class wrapper for them). For example, look at the
following listing: Listing 10. Global function
returns series of numbers in string form (save in file named
listing10.py)
START = 1
SPACER = " "
def CounterString(length):
buffer = ""
for i in range(START, length):
buffer = buffer + str(i) + SPACER
return buffer
print CounterString(10)
|
First we define two global variables used as constants in this program
-- START and SPACER -- one an integer, and one a
string.
Next we define a function, CounterString , using the
def keyword. The function takes a single argument, an integer
called length . The fact that Jython does not explicitly check
that the argument is an integer is an advantage of Jython's dynamic
feature; but it can also be a disadvantage because some sorts of type
errors won't be caught until later than they would be in Java
programming.
Notice that the function signature line ends with a colon and thus
introduces a new block, marked by the indentation in the subsequent lines.
The first line in this new block initializes a string buffer as an empty
string. This buffer will be manipulated to yield the expected function
results.
The next line creates a loop. Jython's for statement is
fundamentally different from the Java language statement. In Java
programming, you set up initial and termination conditions, as well as
each loop step. Jython's loops always walk over a particular sequence from
start to end. The sequence is usually a list, a very important data type
in Jython.
A list of three strings looks like this:
If you want a loop over numbers from 1 to N (as we do
here), you can use the function range() , which returns a list
of numbers in a given range. Some experimentation at the interactive
Jython prompt should help you familiarize yourself with this tool: Listing 11. range() function examples
>>> range(5)
[0, 1, 2, 3, 4]
>>> range(1, 5)
[1, 2, 3, 4]
>>> range(1, 10, 2)
[1, 3, 5, 7, 9]
>>> range(10, 1, -3)
[10, 7, 4]
|
Looking back at Listing
10, each iteration of the for loop runs as a block of
code that is indented an additional step from the rest of the function
body. The block is a single line in which the current buffer is
concatenated to the new number, which is first coerced to a string using
the str() function (rather than a cast as in
Java programming), then a spacer is appended. After this loop terminates,
the resulting buffer is returned. Right after the function body is a line
of code to test it. Again Jython allows you to do this without any special
rigging, such as a main method on an application class. The
output from Listing 10 is shown here: Listing 12.
Output from Listing 10
$ jython listing10.py
1 2 3 4 5 6 7 8 9
|
Building classes as easily as
functions You can create a class in Jython with the same
ease as creating global functions. Listing 13 offers an example: Listing 13. A simple example of a user-defined class (save
in file named listing13.py)
class Dog:
def __init__(self, bark_text):
self.bark_text = bark_text
return
def bark(self):
print self.bark_text
return
def annoy_neighbors(self, degree):
for i in range(degree):
print self.bark_text
return
print "Fido is born"
fido = Dog("Bow wow")
print "Let's hear from Fido"
fido.bark()
print "Time to annoy the neighbors"
fido.annoy_neighbors(5)
|
In the code above, the first line names the class, the definition of
which is all one big code block.
The first method defined is a special one, the initializer
(similar to a Java constructor). It is always named __init__
and is invoked whenever a new instance of the class is created. In Jython
you explicitly declare the current instance being invoked (or in the case
of the initializer, created) as an argument. Traditionally this argument
is called self .
In the Dog initializer, the bark_text
argument, a string, is stored as an instance variable using
self . The method bark() does not take any
explicit parameters when invoked, but you must still specify
self .
The method annoy_neighbors does take a single explicit
argument which is specified in addition to self and is the
number of times the dog is to bark in order to annoy the neighbors. Notice
how easily the code runs to deep nesting, and thus, to indentation.
annoy_neighbors has a loop block within the method definition
within the class definition. The code starting with print "Fido is
born" again demonstrates the class. The output of Listing 13 looks
like this: Listing 14. The output from Listing
13
$ jython listing13.py
Fido is born
Let's hear from Fido
Bow wow
Time to annoy the neighbors
Bow wow
Bow wow
Bow wow
Bow wow
Bow wow
|
Bridging the programming
languages In this article, we've just scratched the surface
of the benefits of adding Jython to your Java programming arsenal:
- The Jython language reduces the amount of code required to perform
tasks.
- The Jython interpreter helps with rapid code development by allowing
you to run code without compilation.
- It allows you to establish global functions and variables which the
Java language doesn't support.
- It introduces dynamic typing, while using inference and casts to
operate properly in the statically-typed virtual machine.
- It introduces the use of generic datatypes (although upcoming Java
versions such as Tiger have also introduced generic types).
- It lets developers easily develop automated testing frameworks.
Through a series of examples, we've also covered some differences in
syntax and typing that a developer should be aware of, including the
syntactical meaning of indentation in Jython and the introduction of an
integer in place of a currently non-supported boolean type.
Using Jython by no means requires that you ditch the Java language.
Jython can be a very handy supplement, useful for quick inspection and
prototyping, testing, and for handling a selection of coding tasks for
which its approach is better suited.
Resources
- Visit the Jython home page to
download the implementation and learn more about how to use it; if
you've already acquired Jython, try these resources for help with installation and platform-specific
issues.
- Jython is an implementation of the Python language; if you plan to
use Jython, you will want to be familiar with the documentation and
other resources hosted at Python.org.
- The developerWorks
Linux zone hosts a regular column devoted to Python, Charming
Python.
- If you're a Java beginner, the "Java
language essentials" tutorial (developerWorks, November 2000)
introduces the Java programming language through examples that
demonstrate the syntax of the language in an object-oriented framework
and standard programming practices. (Some of the examples in this
article are based on examples in that tutorial.)
- In "Diagnosing
Java code: Repls provide interactive evaluation"
(developerWorks, March 2002), Eric Allen delivers an example of
using Jython to build an elegant repl, a
"read-eval-print-loop."
- Join the Jython-users
mailing list, a great place for online help, for interactive
discussions of Jython with fellow developers.
- O'Reilly and Noel Rappin offer "Tips
for Scripting Java with Jython, Part 1," which covers 11 specific
features of Jython that can be particularly time saving or exciting for
Java programmers.
- Jython
Essentials (Samuele Pedroni and Noel Rappin, O'Reilly, March
2002) provides a solid introduction to the Jython, numerous examples of
Jython/Java interaction, and reference material on modules and libraries
of use to Jython programmers. (Chapter 1 is available online.)
- Learn to build Web and enterprise applications with Jython in Python
Programming with the Java Class Libraries (Richard Hightower,
Addison-Wesley/Pearson, June 2002).
- The ActiveState
Programmer Network offers two Jython resources: a simple JSP custom
tag implemented in Jython and a simple Jython servlet.
- Fourthought Inc. is a software
vendor and consultancy specializing in XML solutions for enterprise
knowledge management. Fourthought develops 4Suite, an open source platform for XML,
RDF, and knowledge-management applications.
- This comprehensive set of articles on developing
Web services with Python can help you understand the workings of
Jython development.
- Find hundreds of other Java technology-related articles at the developerWorks
Java technology zone.
About the
author Uche Ogbuji is a consultant and co-founder of Fourthought,
Inc., a software vendor and consultancy specializing in XML
solutions for enterprise knowledge management. Fourthought has
developed 4Suite, an open source platform for XML, RDF, and
knowledge-management applications. Uche is a computer engineer and
writer born in Nigeria; he lives and works in Boulder, Colorado. You
can contact Uche at uche.ogbuji@fourthought.com. |
|
|