从Java程序向Python程序提供自定义输入

3

我正在尝试制作一个完整的Java程序来运行Python程序。Python程序如下:

print('Enter two numbers')
a = int(input())
b = int(input())
c = a + b
print(c)

如果我运行这段代码,终端会显示类似以下内容:
Enter two numbers
5
3
8

现在,我希望在Java中执行此代码时得到相同的输出。以下是我的Java代码:

import java.io.*;
class RunPython {
    public static void main(String[] args) throws IOException {
        String program = "print('Enter two numbers')\na = int(input())\nb = int(input())\nc = a + b\nprint(a)\nprint(b)\nprint(c)";
        FileWriter fileWriter = new FileWriter("testjava.py");
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        bufferedWriter.write(program);
        bufferedWriter.close();
        Process process = Runtime.getRuntime().exec("python testjava.py");
        InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(process.getOutputStream());
        InputStreamReader read = new InputStreamReader(System.in);
        BufferedReader in = new BufferedReader(read);
        String output;
        while (process.isAlive()) {
            while (!bufferedReader.ready());
            System.out.println(bufferedReader.ready());
            while (!(output = bufferedReader.readLine()).isEmpty()) {
                System.out.println(output);
            }
            bufferedReader.close();
            if (process.isAlive()) {
                outputStreamWriter.write(in.readLine());
            }
        }
    }
}

但是,在运行这个程序时,只显示了第一行并接受了第一个输入。之后,程序就没有响应了。 我犯了什么错误?有什么解决方案吗?


你用调试器逐步调试过程序了吗? - tgdavies
尝试在testjava.py中编写Python代码并执行,不使用String程序。 - Decapitated Soul
如果您想避免IO阻塞的副作用,需要以与“手动”输入相同的方式写入进程输入流,并使stdout和stderr能够异步响应。如果您正确地安排了这种方式,您的问题应该会消失。 - g00se
你有考虑过使用Jython来解决问题吗?如果没有,你可以使用类似于Process p = new ProcessBuilder("python", "myScript.py", "firstargument").start();的方法将参数从Java传递到Python脚本中。但是,无论如何,Jython都可以更清晰地完成这两个任务。 - Eno Gerguri
2个回答

3

处理与另一个进程的输入和输出有些混乱,你可以在这里阅读一个很好的答案来了解如何处理:这里

因此,将这些答案应用于您的代码可能是这样的:

import java.io.*;
import java.util.Scanner;

class RunPython {
    public static void main(String[] args) throws IOException {
//        String program = "print('Enter two numbers')\na = int(input())\nprint(a)\nb = int(input())\nprint(b)\nc = a + b\nprint(c)";
        // If you are using Java 15 or newer you can write code blocks
        String program = """
                print('Enter first number')
                a = int(input())
                print(a)
                print('Enter second number')
                b = int(input())
                print(b)
                c = a + b
                print(c)
                """;
        FileWriter fileWriter = new FileWriter("testjava.py");
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        bufferedWriter.write(program);
        bufferedWriter.close();

        Process process =
                new ProcessBuilder("python", "testjava.py")
                        .redirectErrorStream(true)
                        .start();

        Scanner scan = new Scanner(System.in);

        BufferedReader pythonOutput = new BufferedReader(new InputStreamReader(process.getInputStream()));
        BufferedWriter pythonInput = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));

        Thread thread = new Thread(() -> {
            String input;
            while (process.isAlive() && (input = scan.nextLine()) != null) {
                try {
                    pythonInput.write(input);
                    pythonInput.newLine();
                    pythonInput.flush();
                } catch (IOException e) {
                    System.out.println(e.getLocalizedMessage());
                    process.destroy();
                    System.out.println("Python program terminated.");
                }
            }
        });
        thread.start();

        String output;
        while (process.isAlive() && (output = pythonOutput.readLine()) != null) {
            System.out.println(output);
        }
        pythonOutput.close();
        pythonInput.close();
    }
}

请注意,pythonInput 在 Java 中是 BufferedWriter,反之亦然。pythonOutput 是 BufferedReader。

1
使用 Process:
Process p = new ProcessBuilder(
    "python", "myScript.py", "firstargument Custom input to a Python program from a Java program"
).start();

在运行时,您可以添加任意数量的参数。


使用Jython(更简单的选项):
//Java code implementing Jython and calling your python_script.py
import org.python.util.PythonInterpreter;
import org.python.core.*;

public class ImportExample {
   public static void main(String [] args) throws PyException
   {
       PythonInterpreter pi = new PythonInterpreter();
       pi.execfile("path_to_script\\main.py");
       pi.exec("Any custom input from this java program in python to be run");
   }
}

这个页面介绍了如何嵌入Jython,详情请查看此处

注意: 如果你想使用已安装的包,可能需要使用你的python.path初始化解释器。你可以在给定的代码上方添加以下代码来实现:

Properties properties = System.getProperties();
properties.put("python.path", ".\\src\\test\\resources");  // example of path to custom modules (you change this to where the custom modules you would want to import are)
PythonInterpreter.initialize(System.getProperties(), properties, new String[0]);

你也可以返回值,如果需要反向操作,可以在Jython文档中找到。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接