Search code examples
javapythonmultithreadingprocessruntime.exec

Runtime.exec() in java hangs because it is waiting for input from System.in


I have the following short python program "test.py"

n = int(raw_input())
print n

I'm executing the above program from following java program "ProcessRunner.java"

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

public class ProcessRunner {
    public static void main(String[] args) {
        try {
            Scanner s = new Scanner(Runtime.getRuntime().exec("python test.py").getInputStream()).useDelimiter("\\A");
            System.out.println(s.next());
        }

        catch(Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

Upon running the command,

java ProcessRunner

I'm not able to pass a value 'n' in proper format to Python program and also the java run hangs. What is the proper way to handle the situation and pass a value to 'n' dynamically to python program from inside java program?


Solution

  • raw_input(), or input() in Python 3, will block waiting for new line terminated input on standard input, however, the Java program is not sending it anything.

    Try writing to the Python subprocess using the stream returned by getOutputStream(). Here's an example:

    import java.util.*;
    import java.io.*;
    
    public class ProcessRunner {
        public static void main(String[] args) {
            try {
                Process p = Runtime.getRuntime().exec("python test.py");
                Scanner s = new Scanner(p.getInputStream());
                PrintWriter toChild = new PrintWriter(p.getOutputStream());
    
                toChild.println("1234");    // write to child's stdin
                toChild.close();            // or you can use toChild.flush()
                System.out.println(s.next());
            }
    
            catch(Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }
    

    An alternative is to pass n as a command line argument. This requires modification of the Python script to expect and process the command line arguments, and to the Java code to send the argument:

    import java.util.*;
    import java.io.*;
    
    public class ProcessRunner {
        public static void main(String[] args) {
            try {
                int n = 1234;
                Process p = Runtime.getRuntime().exec("python test.py " + n);
                Scanner s = new Scanner(p.getInputStream());
                System.out.println(s.next());
            }
    
            catch(Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }
    

    And the Python script, test.py:

    import sys
    
    if len(sys.argv) > 1:
        print int(sys.argv[1])