How to run Python programs from Java
An easy way to run Python programs from within Java is to invoke
the Jython interpreter to run the Python code.
The Python programs require little or no modification.
Unlike all Java code which must be in OO methods, there is no such requirement
for Python. Procedural Python is fine.
Start by writing and testing your Python program as a Python program;
it's quicker that way. Then include code, like that shown below, in
your Java code.
In following example, the main instantiates a Jython
interpreter, loads a value into num, runs sq.py, and extracts and
prints the answer.
(Everything runs in main, but that is not necessary.)
// file RunSqPy.java
import org.python.util.PythonInterpreter;
import org.python.core.*;
public class RunSqPy {
static public void main(String[] args) throws PyException {
// instantiate the interpreter
PythonInterpreter interp = new PythonInterpreter();
// set runtime args as Jython global variables
interp.set("num", new PyInteger(2));
// cause the Python program to be run (a fully
// qualified pathname is allowed)
interp.execfile("sq.py");
// get values
PyObject sq = interp.get("square");
PyObject num = interp.get("num");
// ...and do with them as you please (you may need
// to cast them depending on usage)
System.out.println("square of " + num + " is " + sq);
}
}
Compile this with javac RunSqPy.java, but before running it, be
sure you have the file sq.py as shown below.
# file: sq.py
# this could be a whole lot more sophisticated, but
# this is sufficient to illustrate how to access
# variables before and after execution.
print '--- sq.py start ---'
if __name__ == '__main__':
num = 7
print 'num =', num
square = num**2
print 'square =', square
print '---- sq.py end ----'
Typing java RunSqPy should yield
--- sq.py start ---
num = 2
square = 4
---- sq.py end ----
square of 2 is 4
but typing python sq.py should give
--- sq.py start ---
num = 7
square = 49
---- sq.py end ----
Remember, only the core Python libraries were ported to Jython.
You will have to make available any other Python modules you need.
Compiling the Java code in Appendix A
(RunPython.java) provides a general purpose Java class to
facilitate the running of Python code.
This cleaner example does the same as RunSqPy.java above.
// file: ShortTestPython.java
import RunPython.*;
public class ShortTestPython {
public static void main(String[] args) {
RunPython py = new RunPython();
py.setInt("num", 2);
py.run("sq.py");
System.out.println("square = " + py.getInt("square"));
}
}
Your Python program might want to have logic that can determine if it is
running standalone (from a command line) or is being called from a Java
program.
A simple declarative technique is
if __name__ == '__main__':
num = 7
If your code needs to run in multiple environments where the value of
a variable can be set set in one of several ways, you will need some way
of detecting whether it has already been set or not. The following
example allows you to not give a value if the variable already
has one.
try: # if not already defined (fm Java), an
junk = num # exception will be thrown
except:
num = 7 # set a default value or inspect the
# command line arguments (sys.argv)
Appendix A: RunPython.java
The use of this Java class, RunPython, is strictly optional, but it
does simplifiy access to the Jython interpreter.
import org.python.util.PythonInterpreter;
import org.python.core.*;
public class RunPython {
// instantiate a fresh interpreter
PythonInterpreter interp = new PythonInterpreter();
// a 'do nothing' constructor
public RunPython() { }
// use this contructor if no variables to be passed
// in and you want to run a Jython program (saves a line)
public RunPython(String filename) {
run(filename);
}
// run the named Jython program
public void run(String filename){
interp.execfile(filename);
}
// gets an integer return value
public int getInt(String name) {
return ((PyInteger) interp.get(name)).getValue();
}
// sets an input integer value
public void setInt(String name, int value){
interp.set(name, new PyInteger(value));
}
// gets a double return value (Python floats are doubles)
public double getDouble(String name) {
return ((PyFloat) interp.get(name)).getValue();
}
// sets an input double value (Python floats are doubles)
public void setDouble(String name, double value){
interp.set(name, new PyFloat(value));
}
// gets a string return value
public String getStr(String name) {
return ((PyString) interp.get(name)).toString();
}
// sets an input string value
public void setStr(String name, String value){
interp.set(name, new PyString(value));
}
// can add more getters and setters for complex,
// list, dictionary, tuple, etc. ...someday.
}
Appendix B: Jython References
An excellent book devoted entirely to Jython is "Jython Essentials" by
Pedroni and Rappin, published by O'Reilly
(ISBN 0-596-00247-5).
Mark Lutz devoted a section to Jpython (Jython) in his book "Programming
Python", also published by O'Reilly
(ISBN 0-596-00085-5).
"The Quick Python Book" also has a section about Jpython. It was written
by Harms and McDonald and is published by Manning
(ISBN 1-884777-74-0).
Bruce Eckel has an extensive description of Jython in the
"Multiple languages" chapter of his book "Thinking in Patterns",
http://64.78.49.204/TIPatterns-0.7.zip.
Bruce has several other free, downloadable books at
http://www.mindview.net/Books.
And, there is some good information at the
Jython web site.