We’ve been using JPype at GEM to integrate some existing legacy Java libraries with the new Python code in OpenQuake. Until today, one of the ugliest parts of this integration has been logging – although we’re using the popular Log4J library to manage log output within the Java code, the Jpype JVM has a separate file descriptor for the console from the Python environment.
To deal with this, I whipped up a quick OutputStream and matching Proxy interface:
package org.gem;import java.io.IOException;import java.io.OutputStream;public class PythonOutputStream extends OutputStream {private IPythonPipe thispipe;public void setPythonStdout(IPythonPipe mypipe) {thispipe = mypipe;}@Overridepublic void write(int arg0) throws IOException {thispipe.write((char) arg0);}package org.gem;public interface IPythonPipe {public void write(char output);}
This interface ends up having the same interface as the python sys.stdout pipe, making the connection between Java and Python as simple as the following:
mystream = jpype.JProxy("org.gem.IPythonPipe", inst=sys.stdout)errstream = jpype.JProxy("org.gem.IPythonPipe", inst=sys.stderr)outputstream = jpype.JClass("org.gem.PythonOutputStream")()err_stream = jpype.JClass("org.gem.PythonOutputStream")()outputstream.setPythonStdout(mystream)err_stream.setPythonStdout(errstream)ps = jpype.JClass("java.io.PrintStream")jpype.java.lang.System.setOut(ps(outputstream))jpype.java.lang.System.setErr(ps(err_stream))
Up next time – how we managed using the same JVM in many modules, plus some bonus notes on setting Java system settings in Jpype.