63

从 Java 执行 Python 脚本并接收该脚本的输出的最简单方法是什么?我寻找过不同的库,例如 Jepp 或 Jython,但大多数都显得过时了。库的另一个问题是,如果我使用库,我需要能够轻松地将库包含在源代码中(尽管我不需要为库本身提供源代码)。

正因为如此,最简单/最有效的方法是简单地做一些事情,比如用 runtime.exec 调用脚本,然后以某种方式捕获打印输出?或者,即使这对我来说很痛苦,我也可以将 Python 脚本输出到一个临时文本文件,然后用 Java 读取该文件。

注意:Java 和 Python 之间的实际通信不是我要解决的问题的要求。然而,这是我能想到的轻松执行需要完成的事情的唯一方法。

4

10 回答 10

75

不确定我是否正确理解了您的问题,但如果您可以从控制台调用 Python 可执行文件并且只想在 Java 中捕获其输出,则可以使用exec()JavaRuntime类中的方法。

Process p = Runtime.getRuntime().exec("python yourapp.py");

您可以阅读如何实际读取此资源的输出:http: //www.devdaily.com/java/edu/pj/pj010016 import java.io.*;

public class JavaRunCommand {

    public static void main(String args[]) {

        String s = null;

        try {
            
        // run the Unix "ps -ef" command
            // using the Runtime exec method:
            Process p = Runtime.getRuntime().exec("ps -ef");
            
            BufferedReader stdInput = new BufferedReader(new 
                 InputStreamReader(p.getInputStream()));

            BufferedReader stdError = new BufferedReader(new 
                 InputStreamReader(p.getErrorStream()));

            // read the output from the command
            System.out.println("Here is the standard output of the command:\n");
            while ((s = stdInput.readLine()) != null) {
                System.out.println(s);
            }
            
            // read any errors from the attempted command
            System.out.println("Here is the standard error of the command (if any):\n");
            while ((s = stdError.readLine()) != null) {
                System.out.println(s);
            }
            
            System.exit(0);
        }
        catch (IOException e) {
            System.out.println("exception happened - here's what I know: ");
            e.printStackTrace();
            System.exit(-1);
        }
    }
}

还有一个 Apache 库(Apache exec 项目)可以帮助您解决这个问题。你可以在这里读更多关于它的内容:

http://www.devdaily.com/java/java-exec-processbuilder-process-1

http://commons.apache.org/exec/

于 2012-04-10T22:48:11.283 回答
34

您可以在 Java 项目中包含Jython库。您可以从 Jython 项目本身下载源代码。

Jython 确实提供了对JSR-223 的支持,它基本上允许您从 Java 运行 Python 脚本。

您可以使用 aScriptContext来配置要将执行输出发送到的位置。

例如,假设您在名为 的文件中有以下 Python 脚本numbers.py

for i in range(1,10):
    print(i)

因此,您可以按如下方式从 Java 运行它:

public static void main(String[] args) throws ScriptException, IOException {

    StringWriter writer = new StringWriter(); //ouput will be stored here
    
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptContext context = new SimpleScriptContext();
    
    context.setWriter(writer); //configures output redirection
    ScriptEngine engine = manager.getEngineByName("python");
    engine.eval(new FileReader("numbers.py"), context);
    System.out.println(writer.toString()); 
}

输出将是:

1
2
3
4
5
6
7
8
9

只要您的 Python 脚本与 Python 2.5 兼容,使用 Jython 运行它就不会出现任何问题。

于 2012-04-10T23:29:01.933 回答
8

我以前遇到过同样的问题,也在这里阅读了答案,但没有发现任何令人满意的解决方案可以平衡兼容性、性能和良好的格式输出,Jython 不能使用扩展 C 包并且比 CPython 慢。所以最后决定自己发明轮子,花了我5个晚上,希望对你也有帮助:jpserve( https://github.com/johnhuang-cn/jpserve )。

JPserve 提供了一种简单的方式来调用 Python 并通过格式良好的 JSON 交换结果,几乎没有性能损失。以下是示例代码。

首先在Python端启动jpserve

>>> from jpserve.jpserve import JPServe
>>> serve = JPServe(("localhost", 8888))
>>> serve.start()

INFO:JPServe:JPServe starting...
INFO:JPServe:JPServe listening in localhost 8888

然后从 JAVA 端调用 Python:

PyServeContext.init("localhost", 8888);
PyExecutor executor = PyServeContext.getExecutor();
script = "a = 2\n"
    + "b = 3\n"
    + "_result_ = a * b";

PyResult rs = executor.exec(script);
System.out.println("Result: " + rs.getResult());

---
Result: 6
于 2016-10-11T09:05:48.737 回答
4

我一直在寻找不同的库,例如 Jepp 或 Jython,但大多数似乎都已经过时了。

Jython 不是“图书馆”;它是在 Java 虚拟机之上的 Python 语言的实现。它绝对不会过时;最近一次发布是今年 2 月 24 日。它实现了 Python 2.5,这意味着您将缺少一些更新的功能,但老实说,它与 2.7 并没有太大区别。

注意:Java 和 Python 之间的实际通信不是上述作业的要求,所以这不是我的功课。然而,这是我能想到的轻松执行需要完成的事情的唯一方法。

这对于学校作业来说似乎极不可能。请告诉我们更多关于你真正想做的事情。通常,学校作业会明确指定您将使用哪些语言,而我从未听说过涉及一种以上语言的语言。如果确实如此,他们会告诉你是否需要建立这种沟通方式,以及他们打算如何让你这样做。

于 2012-04-10T23:15:16.173 回答
3

Jython 方法

Java 应该是平台独立的,并且调用本机应用程序(如 python)并不是非常独立于平台的。

有一个用 Java 编写的 Python (Jython) 版本,它允许我们将 Python 嵌入到我们的 Java 程序中。通常,当您要使用外部库时,一个障碍是编译和正确运行它,因此我们通过 Jython 构建和运行一个简单的 Java 程序的过程。

我们首先获取 jython jar 文件:

https://www.jython.org/download.html

我将 jython-2.5.3.jar 复制到我的 Java 程序所在的目录中。然后我输入了下面的程序,和前两个一样;取两个数字,将它们发送给 python,python 将它们相加,然后 python 将它返回给我们的 Java 程序,其中数字被输出到屏幕上:

import org.python.util.PythonInterpreter; 
import org.python.core.*; 

class test3{
    public static void main(String a[]){

        PythonInterpreter python = new PythonInterpreter();

        int number1 = 10;
        int number2 = 32;
        python.set("number1", new PyInteger(number1));
        python.set("number2", new PyInteger(number2));
        python.exec("number3 = number1+number2");
        PyObject number3 = python.get("number3");
        System.out.println("val : "+number3.toString());
    }
}

我将此文件称为“test3.java”,保存它,然后执行以下操作来编译它:

javac -classpath jython-2.5.3.jar test3.java

下一步是尝试运行它,我执行以下方式:

java -classpath jython-2.5.3.jar:. test3

现在,这允许我们以独立于平台的方式从 Java 中使用 Python。这有点慢。尽管如此,它还是很酷的,它是一个用 Java 编写的 Python 解释器。

于 2017-04-09T11:34:57.160 回答
3

Jep是另一种选择。它通过 JNI将CPython嵌入到 Java 中。

import jep.Jep;
//...
    try(Jep jep = new Jep(false)) {
        jep.eval("s = 'hello world'");
        jep.eval("print(s)");
        jep.eval("a = 1 + 2");
        Long a = (Long) jep.getValue("a");
    }
于 2017-07-04T10:36:10.170 回答
2

ProcessBuilder 非常易于使用。

ProcessBuilder pb = new ProcessBuilder("python","Your python file",""+Command line arguments if any);
Process p = pb.start();

这应该调用 python。有关完整示例,请参阅此处的过程方法!

https://bytes.com/topic/python/insights/949995-three-ways-run-python-programs-java

于 2019-09-10T06:31:46.247 回答
1

您可以尝试使用 groovy。它在 JVM 上运行,并为运行外部进程和提取输出提供了强大的支持:

http://groovy.codehaus.org/Executing+External+Processes+From+Groovy

您可以在来自同一链接的这段代码中看到 groovy 如何轻松获取进程的状态:

println "return code: ${ proc.exitValue()}"
println "stderr: ${proc.err.text}"
println "stdout: ${proc.in.text}" // *out* from the external program is *in* for groovy
于 2012-04-10T23:02:01.217 回答
1

首先,我建议使用 ProcessBuilder(自 1.5 起)
这里描述了简单的用法
https://stackoverflow.com/a/14483787
有关更复杂的示例,请参阅
http://www.javaworld.com/article/2071275/core-java /when-runtime-exec---won-t.html

我在从 Java 启动 Python 脚本时遇到了问题,脚本对标准输出产生了太多的输出,一切都变糟了。

于 2013-12-18T14:54:02.880 回答
0

实现的最佳方法是使用 Apache Commons Exec,因为我将它用于生产,即使对于 Java 8 环境也没有问题,因为它允许您通过使用看门狗以synchronous和方式执行任何外部进程(包括 python、bash 等) asynchronous.

 CommandLine cmdLine = new CommandLine("python");
 cmdLine.addArgument("/my/python/script/script.py");
 DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();

 ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000);
 Executor executor = new DefaultExecutor();
 executor.setExitValue(1);
 executor.setWatchdog(watchdog);
 executor.execute(cmdLine, resultHandler);

 // some time later the result handler callback was invoked so we
 // can safely request the exit value
 resultHandler.waitFor();

此处共享一个小而完整的 POC 的完整源代码,解决了本文中另一个问题;

https://github.com/raohammad/externalprocessfromjava.git

于 2019-05-16T11:09:56.017 回答