在Java中调用和接收Python脚本的输出?

时间:2012-04-10 22:40:52

标签: java python

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

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

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

10 个答案:

答案 0 :(得分:54)

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

Runtime

您可以在这里阅读如何实际读取输出:

http://www.devdaily.com/java/edu/pj/pj010016

还有一个Apache库(Apache exec项目)可以帮助您解决这个问题。你可以在这里阅读更多相关信息:

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

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

答案 1 :(得分:29)

您可以在Java Project中包含Jython库。您可以从Jython项目本身download the source code

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

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

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

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运行此脚本就不会有任何问题。

答案 2 :(得分:7)

之前我遇到了同样的问题,也在这里阅读了答案,但是没有发现任何满足的解决方案可以平衡兼容性,性能和格式输出,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

答案 3 :(得分:5)

  

我找过不同的图书馆,如Jepp或Jython,但大多数图书馆似乎都已过时。

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

  

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

这似乎非常不太适合学校作业。请告诉我们您真正尝试做什么的更多信息。通常,学校作业会准确指定您将使用哪种语言,而我从未听说过涉及多种语言的语言。如果确实如此,他们会告诉你是否需要建立这种沟通,以及他们打算如何做到这一点。

答案 4 :(得分:2)

Jython方法

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

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

我们首先抓住jython jar文件:

http://www.jython.org/downloads.html

我将jython-2.5.3.jar复制到了我的Java程序所在的目录。然后我输入以下程序,它与前两个程序一样;取两个数字,将它们发送到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解释器......

答案 5 :(得分:2)

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

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

答案 6 :(得分: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

答案 7 :(得分: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脚本时遇到了问题 生产出太多产量到标准输出,一切都变坏了。

答案 8 :(得分:0)

实现这一目标的最佳方法是使用Apache Commons Exec,因为即使我在Java 8环境中也可以正常使用它,因为它可以让您在{{中执行任何外部进程(包括python,bash等) 1}}和synchronous的方式使用看门狗。

asynchronous

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

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

答案 9 :(得分:0)

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