java 中的 Runtime.exec() 挂起,因为它正在等待来自 System.in 的输入

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

我有以下简短的 python 程序 "test.py"

n = int(raw_input())
print n

我正在从以下 java 程序 "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());
        }
    }
}

根据运行命令,

java ProcessRunner

我无法将正确格式的值 'n' 传递给 Python 程序,而且 java 运行 挂起。处理这种情况并从 java 程序内部将值动态传递给 'n' 到 python 程序的正确方法是什么?

raw_input(), or input() in Python 3,将阻塞等待标准输入上的新行终止输入,但是,Java 程序不会发送任何内容。

尝试使用 getOutputStream() 返回的流写入 Python 子进程。这是一个例子:

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());
        }
    }
}

另一种方法是将 n 作为命令行参数传递。这需要修改 Python 脚本以预期和处理命令行参数,并修改 Java 代码以发送参数:

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());
        }
    }
}

和 Python 脚本,test.py:

import sys

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

如果我理解正确的话,你希望你的 java 程序将你的 python 脚本的任何输出传递给 System.out,并将你的 java 程序的任何输入传递给你的python 脚本,对吗?

查看以下程序以了解如何执行此操作。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class ProcessRunner {

    public static void main(String[] args) {
        try {
            final Process process = Runtime.getRuntime().exec("/bin/sh");

            try (
                    final InputStream inputStream = process.getInputStream();
                    final InputStream errorStream = process.getErrorStream();
                    final OutputStream outputStream = process.getOutputStream()
            ) {

                while (process.isAlive()) {
                    forwardOneByte(inputStream, System.out);
                    forwardOneByte(errorStream, System.err);
                    forwardOneByte(System.in, outputStream);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static void forwardOneByte(final InputStream inputStream,
                                       final OutputStream outputStream)
    throws IOException {
        if(inputStream.available() <= 0) {
            return;
        }

        final int b = inputStream.read();
        if(b != -1) {
            outputStream.write(b);
            outputStream.flush();
        }
    }
}

注意这段代码只是一个概念演示。它会耗尽您的 cpu 并且无法处理更大的吞吐量。