IPC (inter process communication) between python and java
Asked Answered
S

7

19

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.

Soult answered 28/7, 2010 at 19:16 Comment(2)
Can you load the Java classes independently of starting the GUI?Heptachord
yes, I've got a wrapper using JNISoult
S
5

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.

Soult answered 27/9, 2010 at 14:0 Comment(0)
R
4

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

Recommended.

Ripply answered 12/7, 2013 at 21:0 Comment(1)
this is great. It's heavily relied on O-O model though, so it might not be possible for C like languages. But it answers this question + using sockets to send message.Alkyne
C
3

Named pipes could be the answer for you. See: Create a temporary FIFO (named pipe) in Python?

Carolinian answered 28/7, 2010 at 19:46 Comment(2)
Hrm, this seems easy from the Python angle, but from what I'm reading Java will only be able to treat the FIFOs as files and won't be able to create them in an OS-independent way. This should be fine for sending images to Java, but I'm not sure if it will suffice for getting them back.Soult
FIFOs are platform-dependent and they are in fact used via file interfaces in UNIX (en.wikipedia.org/wiki/Named_pipe). If you're uncomfortable with that (or prefer something supported by standard libraries), you could just use a socket.Carolinian
S
3

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()
Schnauzer answered 15/3, 2020 at 19:51 Comment(0)
A
2

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!).

Accursed answered 28/7, 2010 at 19:41 Comment(0)
T
0

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.

Twentyone answered 25/2, 2016 at 1:57 Comment(1)
It is working only on Linux and MacOS, not WindowsMariano
M
0

Inter-Process Communication between Python and Java



Implementing a self-contained, System independent JRE in the Python application


In order to make the Python application independent of the system as a whole, a JRE must be created inside the Python application. This must be done if it is desired that the application must not depend on the system and everything must be self-contained within the application. This is helpful if the application as a whole must be ready to run on any user's machine without any additional resources and procedures upon each installation.

Go to https://learn.microsoft.com/en-us/java/openjdk/download, download the JDK for your desired hardware architecture and OS, and load it inside the Python application's environment. Afterwards put the Java application project as a whole or a .jar file made from the Java application within the Python application's directory.

enter image description here

You can then launch the Java application within the Python application as a sub-process.



Inter-Process communication methods


Real-time Inter-Process Communication using stdin, stout and stderr



The stdin,stdout , and stderr streams are the main I/O systems that the OS kernel is using for applications and processes. By modifying the flow of these streams from child process to OS, to child process to parent process, these streams will be bypassed through the parent process and the parent process will have the ability to perform input and output operations directly with the child process


[ Java Code ]

public class Main {

    public static void main(String[] args)
    {
        // Send input over the "stdout" stream to the Python parent process
        System.out.println("Message from Java application");
        System.out.flush();

        // Read input over the "stdin" stream from the Python parent process
        Scanner s = new Scanner(System.in);
        String input = s.nextLine();
        s.close();

        // Send input over the "stdout" stream to the Python parent process
        System.out.println(input);
        System.out.flush();
    }
}

[ Python Code ]

import subprocess

# Path to java.exe, in case the application contains a self-contained java environment, else just the "java" command
path_to_java_exe = "C:\\Users\\Teodor Mihail\\PycharmProjects\\Python_IPC\\jre\\bin\\java.exe"

# Command line argument that specifies the compiler what it should compile, in this case is a ".jar" file
java_exe_arguments = "-jar"

# The path to the file that the compiler will run and the runtime will execute, in this case it is the whole program compiled as a ".jar" file
java_jar_file_path = "C:\\Users\\Teodor Mihail\\PycharmProjects\\Python_IPC\\Java_I.P.C.jar"

# Global variable that holds the sub-process
process = None




def subprocess_startup():
    # Specify that the "process" variable is a reference to the global variable "process"
    global process

    # Open the process and redirect the "stdin", "stdout", and "stderr" streams from the sub-process to the OS to the Python process
    process = subprocess.Popen([path_to_java_exe, java_exe_arguments, java_jar_file_path], stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE, stderr=subprocess.PIPE)


def subprocess_read_stdout():
    # Read the output sent by the Java application sub-process over the "stdout" stream
    received = process.stdout.readline()
    print(received)


def subprocess_write_stdin(data):
    # Write input to the Java application over the "stdin" stream
    process.stdin.write(data.encode("utf-8"))
    process.stdin.flush()


def main():
    subprocess_startup()

    # A loop can be implemented here for continuous read and write operations.
    # Both the read and write operation methods can be open on different threads
    # to perform continuous read and write operations executed in parallel


    subprocess_read_stdout()

    # Data to be written on the stdin stream must end in "\n" otherwise the Java
    # Scanner will lock. This will happen because the Scanner in Java is
    # scanning until a "\n" is found, otherwise it will wait indefinitely
    # until it will find a "\n" within the input stream.
    subprocess_write_stdin("Message from Python application\n")



    subprocess_read_stdout()


if __name__ == '__main__':
    main()

At each process.stdin.write method call, the data sent to the child process must be terminated with a newline character ("\n"). This must be done because the Java scanner will scan the stdin stream looking for a newline character, and because the stream is buffered, this will result into a lock on the thread on which this operation is performed.



Mariano answered 9/5, 2023 at 22:17 Comment(1)
can you please crop your screenshots to get rid of all the huge wasted space that isn't relevant?Dipnoan

© 2022 - 2025 — McMap. All rights reserved.