简体   繁体   中英

Issue in calling Python code from Java (without using jython)

I found this as one of the ways to run (using exec() method) python script from java. I have one simple print statement in python file. However, my program is doing nothing when I run it. It neither prints the statement written in python file nor throws an exception. The program just terminates doing nothing:

Process p = Runtime.getRuntime().exec("C:\\Python\\Python36-32\\python.exe C:\\test2.py");

Even this is not creating the output file:

Process p = Runtime.getRuntime().exec("C:\\Python\\Python36-32\\python.exe C:\\test2.py output.txt 2>&1");

What is the issue?

I think you could try your luck with the ProcessBuilder class.

If I read the Oracle documentation correctly, the std inputs and outputs are directed to pipes by default but the ProcessBuilder has an easy method for you to explicitly set output (or input) to a file on your system or something else .

If you want your Python program to use the same output as your Java program (likely stdout and stderr), you can use stg like this:

ProcessBuilder pb = new ProcessBuilder("C:\\Python\\Python36-32\\python.exe", "C:\\test2.py");
pb.redirectOutput(Redirect.INHERIT);
Process p = pb.start();

You can use the ProcessBuilder API, redirecting the output to a file and then wait for the result.

public class Main {

    public static final String PYTHON_PATH = "D:\\Anaconda3\\python.exe";
    public static final String PATH_TO_SCRIPT = "D:\\projects\\StartScript\\test.py";

    public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder builder = new ProcessBuilder();
        builder.command(PYTHON_PATH, PATH_TO_SCRIPT);

        // Redirect output to a file
        builder.redirectOutput(new File("output.txt"));

        builder.start().waitFor();

        // Print output to console
        ProcessBuilder.Redirect output = builder.redirectOutput();
        File outputFile = output.file();
        BufferedReader br = new BufferedReader(new FileReader(outputFile));

        String st;
        while ((st = br.readLine()) != null) {
            System.out.println(st);
        }

    }
}

The python file test.py contains a simple print statement:

print("Hello from python")

I guess it would be even simpler, if you do not need to wait for the result.

Using the Process API should work, too.

Like in your example (I am using the same constants declared above):

Process p = Runtime.getRuntime().exec(PYTHON_PATH + " " + PATH_TO_SCRIPT);
p.waitFor();

byte[] buffer = new byte[1024];
byte[] errBuffer = new byte[1024];

p.getInputStream().read(buffer);
p.getErrorStream().read(errBuffer);

System.out.println(new String(buffer));
System.out.println(new String(errBuffer));

To see the output of the print statement, you need to wait and redirect the streams. Same for the error stream.

Now if you break the python script like this:

print("Hello from python')

you should be able to see the error printed as well.

One way to start a python process is using an entrypoint - test.cmd

echo Hello
python hello.py

here is hello.py

#!/usr/bin/env python3
import os
if not os.path.exists('dir'):
    os.makedirs('dir')

Here is my Java code:

public static void main(String[] args) throws IOException {
    try {
        Process p = Runtime.getRuntime().exec("test.cmd");
        p.waitFor();
        Scanner sc = new Scanner(p.getInputStream());
        while(sc.hasNextLine()){
            System.out.println(sc.nextLine());
        }
        sc.close();
    } catch (Exception err) {
        err.printStackTrace();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM