Calling Python from Java

The jtypes.javabridge loads a Java class, org.cellprofiler.javabridge.CPython, that can be used to execute Python code. The class can be used within Java code called from the Python interpreter or it can be used within Java to run Python embedded in Java.

class org.cellprofiler.javascript.CPython()

The CPython class binds the Python interpreter to the JVM and provides the ability to execute Python scripts.

org.cellprofiler.javascript.CPython.exec()
Arguments:
  • script – The Python script to execute.
  • locals – A map of the name of a Java object in the Python execution context to the Java object itself. The objects in the map have local scope. A null value can be used if no locals need to be defined.
  • globals – A map of the name of a Java object to the Java object itself. The objects in the map have global scope. If a null value is used, globals defaults to the builtin globals.

exec() executes the script passed within the Python interpreter. The interpreter adds the builtin globals to the globals passed in, then executes the script. The same map may be used for both the locals and the globals - this mode may seem more familiar to those who regularly script in Python and expect the import statement to have a global effect.

There is no eval method. You can retrieve values by passing a container object such as an array or map as one of the locals and you can set elements in the object with values to be returned.

Example:

class MyClass {
    static final CPython cpython = CPython();

    public List<String> whereIsWaldo(String root) {
         ArrayList<String> result = new ArrayList<String>();
         Hashtable locals = new Hashtable();
         locals.put("result", result);
         locals.put("root", root);
         StringBuilder script = new StringBuilder();
         script.append("import os\n");
         script.append("from jt import javabridge\n");
         script.append("root = javabridge.to_string(root)");
         script.append("result = javabridge.JWrapper(result)");
         script.append("for path, dirnames, filenames in os.walk(root):\n");
         script.append("  if 'waldo' in filenames:");
         script.append("     result.add(path)");
         cpython.exec(script.toString(), locals, null);
         return result;
    }

}
org.cellprofiler.javascript.CPython.execute()

execute is a synonym for exec which is a Python keyword. Use execute in place of exec to call Python from a jtypes.javabridge CWrapper for CPython.

Maintaing references to Python values

You may want to maintain references to Python objects across script executions. The following functions let a Java caller refer to a Python value (which can be a base type or an object) via a token which may be exchanged for the value at any time. The Java code is responsible for managing the reference’s lifetime. Example:

from jt import javabridge

cpython = javabridge.JClassWrapper('org.cellprofiler.javabridge.CPython')()
d = javabridge.JClassWrapper('java.util.Hashtable')()
result = javabridge.JClassWrapper('java.util.ArrayList')()
d.put("result", result)
cpython.execute(
    'from jt import javabridge\n'
    'x = { "foo":"bar"}\n'
    'ref_id = javabridge.create_and_lock_jref(x)\n'
    'javabridge.JWrapper(result).add(ref_id)', d, d)
cpython.execute(
    'from jt import javabridge\n'
    'ref_id = javabridge.to_string(javabridge.JWrapper(result).get(0))\n'
    'assert javabridge.redeem_jref(ref_id)["foo"] == "bar"\n'
    'javabridge.unlock_jref(ref_id)', d, d)