python和java之间的进程间通信

erhoui1w  于 2023-05-12  发布在  Java
关注(0)|答案(7)|浏览(416)

首先,解释一下我为什么要问这个问题:我正在编写一个python程序(使用wxPython gui),它需要从python调用Java AWT程序并从中提取数据。我在Windows上有一个进程中的工作解决方案。我也有一个在OSX上的进程内解决方案,只要我运行Java应用程序。不幸的是,我没有找到在OSX上的同一进程中运行两个GUI的合理解决方案,因为AWT和WX都需要第一个线程,不能共享wx消息循环。
我想做的是在一个独立于Python程序的进程中启动一个Java程序,并建立一个管道或队列或其他东西来来回传递数据(特别是字节数组)。
我非常感谢任何建议,甚至是在正确的方向上的推动,因为我对IPC的经验很少。

6tqwzwtp

6tqwzwtp1#

我尝试使用管道编写解决方案,但似乎它们不太适合来回发送可能附带大量数据的多条消息。相反,它们似乎非常适合于打开一个运行、响应和死亡的“工人”风格的程序。
在研究socket编程时,我在这里找到了一个很棒的资源:https://web.archive.org/web/20080913064702/http://www.prasannatech.net/2008/07/socket-programming-tutorial.html
本教程介绍了用4种语言编写的简单聊天程序的TCP和UDP变体。我最终使用并修改了TCP Java客户端和Python服务器。

w8f9ii69

w8f9ii693#

这是Google用来在Java和Python之间进行IPC的开源解决方案。https://code.google.com/p/protobuf/
推荐。

lxkprmvk

lxkprmvk4#

python中使用subprocess的IPC
IPC.java 文件这里的java代码将接收数字并发送它的平方。

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 文件

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()
jucafojl

jucafojl5#

使用subprocess.Popen启动Java进程并建立与之通信的管道。为了以一种语言无关、平台无关、可扩展的方式有效地序列化和反序列化数据,请参阅Protocol Buffers(由Jon Skeet!).

eivgtgni

eivgtgni6#

我也遇到过类似的情况,我必须在Java进程和Linux进程之间进行通信。我使用命名管道。
尝试在python中实现mkfifo()。

qvk1mo1f

qvk1mo1f7#

Python与Java的进程间通信

在Python应用中实现一个独立的、系统无关的JRE

为了使Python应用程序独立于整个系统,必须在Python应用程序内部创建JRE。如果希望应用程序不依赖于系统,并且所有内容都必须在应用程序中自包含,则必须这样做。如果应用程序作为一个整体必须准备好在任何用户的机器上运行,而每次安装时都不需要任何额外的资源和过程,那么这是很有帮助的。
转到https://learn.microsoft.com/en-us/java/openjdk/download,下载所需硬件体系结构和操作系统的JDK,并将其加载到Python应用程序的环境中。然后将Java应用程序项目作为一个整体或将Java应用程序生成的.jar文件放入Python应用程序的目录中。

然后,您可以在Python应用程序中将Java应用程序作为子进程启动。

进程间通信方式

使用 stdinstoutstderr 实现实时进程间通信

stdinstdoutstderr流是操作系统内核用于应用程序和进程的主要I/O系统。通过修改从子进程到OS、到子进程到父进程的这些流的流动,这些流将通过父进程被绕过,并且父进程将具有直接与子进程执行输入和输出操作的能力

[ Java代码]

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代码]

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()

在每个process.stdin.write方法调用中,发送到子进程的数据必须以换行符(“\n”)终止。必须这样做,因为Java扫描器将扫描stdin流,查找换行符,而且由于流是缓冲的,这将导致执行此操作的线程锁定。

相关问题