【发布时间】:2020-07-19 02:14:05
【问题描述】:
2020 年 4 月更新:我接受了下面的答案,因为它为我的问题提出了一个非常好的和简单的解决方案,但我的代码一直无法工作!如果有人已经构建了类似的东西,请与我联系!
我有一个简单的脚本my-script.py,它使用Python 编写的特定库非常快速地进行一些计算:
import sys
import special-library
def fun(x):
do something
fun(sys.argv[1])
在我的Java 代码中,我使用ProcessBuilder 方法在代码的不同部分大量使用/调用此脚本,这意味着我只需运行命令python my-script.py argument。
这意味着每次调用这个脚本时,我都要执行import命令,这是其中最耗时的事情(计算部分实际上更快)。
是否有解决方案让我只调用一次导入?我看了一点Jython - 是否可以编写一个类或一些可以启动的东西并进行一次导入,然后每次我想做计算部分时调用它的函数(fun)?有没有人做过类似的事情或有任何其他解决方案?
首次尝试实施
我尝试编写一个“管道”Java 类,它会执行一次 python 脚本。现在脚本从标准输入连续读取,当它得到输入argument时,它会进行计算并返回结果:
import sys
import special-library
def fun(x):
do something
print('END')
for arg in sys.stdin:
fun(arg)
当我从命令行对其进行测试并为其提供输入参数时,这当然有效。
Java类如下:
package my.package;
import java.io.*;
public class PythonScriptExecuter {
private static BufferedReader pythonToJavaReader;
private static PrintWriter javaToPythonWriter;
public PythonScriptExecuter() throws Exception {
String MPBNScriptFile = "fullPathToScriptFile";
ProcessBuilder pb = new ProcessBuilder("python", MPBNScriptFile);
pb.redirectErrorStream(true);
// Start script
Process p = pb.start();
pythonToJavaReader = getOutputReader(p); // from python to java
javaToPythonWriter = getInputWriter(p); // from java to python
}
// Python => Java
private static BufferedReader getOutputReader(Process p) {
return new BufferedReader(new InputStreamReader(p.getInputStream()));
}
// Java => Python
private static PrintWriter getInputWriter(Process p) {
return new PrintWriter(new OutputStreamWriter(p.getOutputStream()));
}
public static Arraylist<String> getResults(String argument) throws IOException {
// send argument to python script
javaToPythonWriter.println(argument);
//javaToPythonWriter.flush();
// get results back one by one
ArrayList<String> results = new ArrayList<>();
int count = 0;
String line;
while (!(line = pythonToJavaReader.readLine()).equals("END")) {
// process `line` string
results.add(line);
}
return results;
}
}
所以,我所做的是在我的代码的初始化部分的某个地方,我有这个简单的行来启动这个过程:
new MPBNPythonScriptExecuter();
后来当我想得到一些结果时,我使用:
String arg = "something"
Arraylist<String> res = PythonScriptExecuter.getResults(arg);
整个事情都挂在从脚本读取输出的行上:
while (!(line = pythonToJavaReader.readLine()).equals("END"))
你知道这里出了什么问题吗?
【问题讨论】:
-
你确认你的python脚本没有错误吗?也需要用类似这样的东西来捕捉错误 while ((ligne = error.readLine()) != null) { System.out.println("err: "+ ligne); }
-
不,它更像是它没有以某种方式正确读取(可能在正确的时间)......当我杀死 java 程序时,有时我可以看到 while 循环内的输出(我打印
line) - 但只有到那时 - 就像它被卡住了一样......