【问题标题】:Custom input to a Python program from a Java program从 Java 程序到 Python 程序的自定义输入
【发布时间】:2021-07-27 10:48:11
【问题描述】:

我正在尝试制作一个运行 python 程序的成熟 Java 程序。 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());
            }
        }
    }
}

但是在运行这个程序时,只显示第一行,并采用第一个输入。之后,程序没有响应。 我犯了什么错误?解决办法是什么?

【问题讨论】:

  • 您是否使用调试器单步执行了您的程序?
  • 尝试在testjava.py中编写Python代码,不使用String Program执行
  • 如果要避免 IO 阻塞副作用,您需要以与“手动”输入相同的方式写入流程输入流,并让 stdout 和 stderr 能够异步响应。如果你以正确的方式安排它,你的问题应该会消失
  • 您是否曾研究过 Jython 的解决方案?如果不是,您可以使用Process p = new ProcessBuilder("python", "myScript.py", "firstargument").start(); 之类的东西将参数从java 传递到python 脚本。但无论如何,Jython 都可以以更清晰的方式做到这两点。

标签: java python process


【解决方案1】:

处理输入和输出到另一个进程有点乱,你可以阅读 一个很好的答案here

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

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。

【讨论】:

    【解决方案2】:

    使用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,可以阅读有关 here 的信息。

    注意:如果您想使用已安装的任何软件包,您可能需要使用 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 documentation中找到

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-03
      • 1970-01-01
      • 2017-03-15
      • 1970-01-01
      • 2011-11-03
      • 2017-06-17
      • 2016-04-22
      相关资源
      最近更新 更多