![](/img/trans.png)
[英]How to run python script (and receive output) from java/spring-boot project which is inside a docker container?
[英]Call and receive output from Python script in Java?
從 Java 執行 Python 腳本並接收該腳本的 output 的最簡單方法是什么? 我尋找過不同的庫,如 Jepp 或 Jython,但大多數都已過時。 庫的另一個問題是,如果我使用一個庫,我需要能夠輕松地將一個庫包含在源代碼中(盡管我不需要為庫本身提供源代碼)。
因此,最簡單/最有效的方法是簡單地做一些事情,比如用 runtime.exec 調用腳本,然后以某種方式捕獲打印的 output? 或者,即使這對我來說會很痛苦,我也可以將 Python 腳本 output 保存到臨時文本文件中,然后讀取 Java 中的文件。
注意:Java 和 Python 之間的實際通信不是我要解決的問題的要求。 然而,這是我能想到的輕松執行需要完成的工作的唯一方法。
不確定我是否正確理解你的問題,但前提是你可以從控制台調用 Python 可執行文件並且只想在 Java 中捕獲它的 output,你可以在 Java Runtime
class 中使用exec()
方法。
Process p = Runtime.getRuntime().exec("python yourapp.py");
您可以從以下資源中了解如何實際讀取 output: 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 執行項目)可以幫助您解決這個問題。 你可以在這里讀更多關於它的內容:
http://www.devdaily.com/java/java-exec-processbuilder-process-1
您可以在 Java 項目中包含Jython庫。 您可以從 Jython 項目本身下載源代碼。
Jython 確實提供了對JSR-223 的支持,它基本上允許您從 Java 運行 Python 腳本。
您可以使用ScriptContext
來配置要將執行的 output 發送到的位置。
例如,假設您在名為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());
}
output 將是:
1
2
3
4
5
6
7
8
9
只要您的 Python 腳本與 Python 2.5 兼容,您就可以使用 Jython 運行它。
我以前遇到過同樣的問題,也在這里閱讀了答案,但沒有找到任何令人滿意的解決方案可以平衡兼容性、性能和格式化 output,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
我尋找過不同的庫,如 Jepp 或 Jython,但大多數似乎都已經過時了。
Jython 不是“圖書館”; 它是 Java 虛擬機之上的 Python 語言的實現。 它絕對不會過時; 最近一次發布是今年 2 月 24 日。 它實現了 Python 2.5,這意味着您將缺少一些較新的功能,但老實說它與 2.7 沒有太大區別。
注意:Java 和 Python 之間的實際通信不是上述作業的要求,所以這不是我的功課。 然而,這是我能想到的輕松執行需要完成的工作的唯一方法。
這對於學校作業來說似乎極不可能。 請告訴我們更多關於您真正想做的事情。 通常,學校作業會明確指定您將使用哪種語言來做什么,而且我從未聽說過涉及一種以上語言的作業。 如果是這樣,他們會告訴你是否需要建立這種溝通方式,以及他們打算如何進行。
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");
}
Jython 方法
Java 應該是獨立於平台的,調用本機應用程序(如 python)並不是非常獨立於平台。
Java 中有一個 Python (Jython) 版本,它允許我們將 Python 嵌入到我們的 Java 程序中。 通常,當您要使用外部庫時,一個障礙是正確編譯和運行它,因此我們 go 完成了使用 Jython 構建和運行一個簡單程序 Java 的過程。
我們首先獲取 jython jar 文件:
https://www.jython.org/download.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 解釋器。
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
您可以嘗試使用 groovy。它在 JVM 上運行,並且非常支持運行外部進程和提取 output:
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
首先,我建議使用 ProcessBuilder(自 1.5 起)
這里描述了簡單的用法
https://stackoverflow.com/a/14483787
有關更復雜的示例,請參閱
http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html
我在從 Java 啟動 Python 腳本時遇到了問題,腳本產生了太多的 output 到標准輸出,一切都變壞了。
實現的最佳方法是使用 Apache Commons Exec,因為我將它用於生產,即使對於 Java 8 環境也沒有問題,因為它允許您以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();
此處共享了一個小而完整的 POC 的完整源代碼,解決了本文中的另一個問題;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.