Run python script from java as subprocess

Tobiq :

I'm trying to execute python code (live from the console, not just opening a single file).

ProcessBuilder builder = new ProcessBuilder("python");
Process process = builder.start();
new Thread(() -> {
    try {
        process.waitFor();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();
new Thread(() -> {
    String line;
    final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    // Ignore line, or do something with it
    while (true) try {
        if ((line = reader.readLine()) == null) break;
        else System.out.println(line);
    } catch (IOException e) {
        e.printStackTrace();
    }
}).start();

final PrintWriter writer = new PrintWriter(new OutputStreamWriter(process.getOutputStream()));
writer.println("1");
writer.println("2 * 2");

I tried this code, but after trying to push the following expressions 1 and 2*2, I don't get a response (evaluation of my expressions).

Does anyone know what the issue is?

Elliott Frisch :

Your python code doesn't appear to print anything, and handling multiple threads to read and write to another process is a tricky topic; luckily, the functionality is built-in. You could do

ProcessBuilder builder = new ProcessBuilder("/usr/bin/env", "python",
        "-c", "print(2*2); exit()");
builder.inheritIO();
try {
    Process process = builder.start();
    process.waitFor();
} catch (Exception e) {
    e.printStackTrace();
}

Which outputs

4

and terminates. For less trivial Python and Java integration, I would strongly suggest you look here. As for your existing code, you never exit() python and you never flush() your PrintWriter. And you write on the main thread. And you need to pass -i to python, or it won't assume stdin is a console. Changing your code to

ProcessBuilder builder = new ProcessBuilder("/usr/bin/env", "python", "-i");
Process process = builder.start();

new Thread(() -> {
    String line;
    final BufferedReader reader = new BufferedReader(
            new InputStreamReader(process.getInputStream()));
    // Ignore line, or do something with it
    while (true)
        try {
            if ((line = reader.readLine()) == null)
                break;
            else
                System.out.println(line);
        } catch (IOException e) {
            e.printStackTrace();
        }
}).start();
new Thread(() -> {
    final PrintWriter writer = new PrintWriter(
            new OutputStreamWriter(process.getOutputStream()));
    writer.println("1");
    writer.println("2 * 2");
    writer.println("exit()");
    writer.flush();
}).start();

Seems to work properly.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=416252&siteId=1