16
votes

First, a little explanation of why I'm asking this question in the first place: I'm writing a python program (with a wxPython gui) that needs to call a Java AWT program from python and extract data from it. I have an in-process working solution on Windows. I also have an in-process solution on OSX so long as I run the Java app headless. Unfortunately there is no reasonable solution that I have found for running both GUIs within the same process on OSX because both AWT and WX both want the first thread and cannot share the wx message loop.

What I would like to do is to launch a Java program in a separate process from my Python program and establish a pipe or queue or something for passing data (specifically byte arrays) back and forth.

I'd greatly appreciate any suggestions, or even a nudge in the right direction as I have very little experience with IPC.

6
Can you load the Java classes independently of starting the GUI? - Ignacio Vazquez-Abrams
yes, I've got a wrapper using JNI - Adam Fraser

6 Answers

4
votes

I attempted to code a solution using pipes but it seems that they just aren't well suited to sending multiple messages back and forth with potentially large data attached. Rather, they seem ideal for opening a "worker" style program that runs, responds, and dies.

Looking into socket programming, I found a fantastic resource here: https://web.archive.org/web/20080913064702/http://www.prasannatech.net/2008/07/socket-programming-tutorial.html

The tutorial presents TCP and UDP variants of a simple chat program written in 4 languages. I ended up using and modifying the TCP Java client and Python server.

3
votes

This is the opensource solution Google uses to do IPC between Java and Python. https://code.google.com/p/protobuf/

Recommended.

1
votes

Use subprocess.Popen to start the Java process and establish pipes to communicate with it. For serializing and deserializing data efficiently in a language-neutral, platform-neutral, extensible way, take a look at Protocol Buffers (contributed to by Jon Skeet!).

0
votes

I had a similar situation where I had to communicate between a Java process and a Linux process. I used named pipes.

Try mkfifo() implementation in python.

0
votes

IPC using subprocess from in python

IPC.java file here java code will receive number and send square of it.

import java.util.Scanner;

public class IPC {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String data="";
        while(scanner.hasNext()){
            // Receive data from Python code 
            data = scanner.nextLine();

            // Process data (calculate square)
            int x = Integer.parseInt(data);
            int square = x*x;


            // Send data to python code
            System.out.println(square);
        }
        scanner.close();
    }
}

IPC.py file

import subprocess
subprocess.run(["javac", "IPC.java"])
proc = subprocess.Popen(["java", "IPC"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
for i in range(10):
    # Send to java code
    proc.stdin.write(b'%d\n' % i)
    proc.stdin.flush()
    proc.stdout.flush()

    # Receive data from java code
    output = proc.stdout.readline()
    print (output.rstrip())
proc.communicate()