Java中的Runtime.exec()因等待System.in输入而挂起。

4

我有以下短小的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程序内部动态地向Python程序传递一个值到“n”?


在这里查看https://dev59.com/SGMk5IYBdhLWcg3w3xhY,了解如何与Python进程通信的信息。 - Ilja Everilä
参见当Runtime.exec()无法正常工作,了解正确创建和处理进程的许多好技巧。然后忽略它所指的exec,使用ProcessBuilder来创建进程。同时,将一个字符串参数arg拆分成String[] args,以考虑包含空格字符的路径等情况。 - Andrew Thompson
2个回答

3

raw_input()input()在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]) 

完美!这正是我在寻找的 :) - Sai Nikhil
如果外部程序是Java程序而不是Python程序,则即使我遵循上述相同的过程,它仍然会挂起。 - Sai Nikhil

0

如果我理解正确的话,您想让您的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,并且无法处理更大量的吞吐量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接