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

调用并接收Java中Python脚本的输出?,java,python,Java,Python,从Java执行Python脚本并接收脚本输出的最简单方法是什么?我已经寻找了不同的库,如Jepp或Jython,但大多数都过时了。库的另一个问题是,如果我使用库,我需要能够轻松地将库包含在源代码中(尽管我不需要为库本身提供源代码) 因此,最简单/最有效的方法是使用runtime.exec调用脚本,然后以某种方式捕获打印输出吗?或者,即使这对我来说非常痛苦,我也可以将Python脚本输出到一个临时文本文件,然后用Java读取该文件 注意:Java和Python之间的实际通信不是我试图解决的问题的要

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

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


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

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

Process p = Runtime.getRuntime().exec("python yourapp.py");
您可以了解如何实际读取此资源的输出: 导入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库(apacheexec项目)可以帮助您实现这一点。您可以在此处阅读更多信息:


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

您可以从同一链接的代码中看到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
我找过不同的库,比如Jepp或Jython,但大多数库似乎已经过时了

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

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

对于学校作业来说,这似乎不太可能。请告诉我们更多关于你真正想做的事情。通常,学校作业会明确说明你将使用什么语言来完成什么任务,而我从来没有听说过一种作业会涉及一种以上的语言。如果有,他们会告诉您是否需要设置这种通信,以及他们打算如何设置。

您可以在Java项目中包含该库。你可以从Jython项目本身开始

Jython确实提供了支持,基本上允许您从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运行该脚本就不会有任何问题。

首先,我建议使用ProcessBuilder(从1.5开始)
这里介绍了简单的用法

有关更复杂的示例,请参阅

我在从Java启动Python脚本时遇到了问题,脚本
生产的产品太多,无法达标,结果一切都糟了

我以前也遇到过同样的问题,也在这里阅读了答案,但没有发现任何令人满意的解决方案可以平衡兼容性、性能和良好的格式输出,Jython无法与extend C软件包一起工作,而且速度比CPython慢。所以最后我决定自己发明轮子,花了我5个晚上的时间,我希望它也能帮助你: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

Jython方法

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

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

我们首先获取jython jar文件:

我将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解释器。

是另一种选择。它通过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");
    }

最好的实现方法是使用ApacheCommonsExec,就像我在生产中使用它一样,即使在Java8环境中也没有问题,因为它允许您使用看门狗以
synchronous
asynchronous
的方式执行任何外部进程(包括python、bash等)

 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();
完整的源代码
ProcessBuilder pb = new ProcessBuilder("python","Your python file",""+Command line arguments if any);
Process p = pb.start();