运行 Python 脚本到 Java 只导入一次
Run Python script through Java with importing just once
2020 年 4 月更新:我接受了下面的答案,因为它为我的问题提出了一个非常好的和简单的解决方案,但我的代码一直没有运行!如果有人已经构建了类似的东西,请与我联系!
我有一个简单的脚本 my-script.py
,它使用用 Python
编写的特定库非常快速地进行一些计算:
import sys
import special-library
def fun(x):
do something
fun(sys.argv[1])
在我的 Java
代码中,我 use/call 这个脚本在代码的不同部分使用了 ProcessBuilder
方法,这意味着我只是 运行命令 python my-script.py argument
。
这意味着我每次调用这个脚本时,我都必须执行 import
命令,这是其中最 耗时 的事情(计算部分实际上更快)。
是否有解决方案让我只调用一次导入?我看了一下 Jython
- 可以写一个 class 或一些会被启动的东西,然后做一次导入,然后每次我想做计算部分时调用它的一个函数(fun
)?有没有人做过类似的事情或对此有任何其他解决方案?
第一次尝试实施
我试过写一个 'pipe' Java Class 来执行一次 python 脚本。现在脚本从 stdin 连续读取,当它获得输入 argument
时,它会进行计算并 returns 结果:
import sys
import special-library
def fun(x):
do something
print('END')
for arg in sys.stdin:
fun(arg)
当我从命令行测试它并为其提供输入参数时,这当然有效。
JavaClass如下:
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"))
知道这里出了什么问题吗?
您可以使用管道在 java 和 Python 之间进行通信。
你 运行 你的 Python 和现在一样(没有命令行参数)
Python 脚本
你在 python 中写了一个无限循环,它将
从
标准输入(它将是您的函数参数)
你调用你的函数
你把答案写到标准输出
Java
写一个发送参数到python
的方法
将函数的参数写入管道
从管道中读取答案
大功告成。
这是一些片段
这里是你如何创建你的管子
Process p = Runtime.getRuntime().exec(commande);
BufferedReader output = getOutput(p); //from python to java
BufferedReader error = getError(p); //from python to java
PrintWriter input = getInput(p); //from java to python
private static BufferedReader getOutput(Process p) {
return new BufferedReader(new InputStreamReader(p.getInputStream()));
}
private static BufferedReader getError(Process p) {
return new BufferedReader(new InputStreamReader(p.getErrorStream()));
}
private static PrintWriter getInput(Process p){
return new PrintWriter (new OutputStreamWriter(p.getOutputStream()));
}
在您的 Python 脚本中尝试以下操作:
import sys
def fun(x):
print(x)
print('END')
sys.stdout.flush()
while 1:
try:
line = sys.stdin.readline()
except KeyboardInterrupt:
break
if not line:
break
fun(line)
您的 Java 代码应该或多或少是正确的。
2020 年 4 月更新:我接受了下面的答案,因为它为我的问题提出了一个非常好的和简单的解决方案,但我的代码一直没有运行!如果有人已经构建了类似的东西,请与我联系!
我有一个简单的脚本 my-script.py
,它使用用 Python
编写的特定库非常快速地进行一些计算:
import sys
import special-library
def fun(x):
do something
fun(sys.argv[1])
在我的 Java
代码中,我 use/call 这个脚本在代码的不同部分使用了 ProcessBuilder
方法,这意味着我只是 运行命令 python my-script.py argument
。
这意味着我每次调用这个脚本时,我都必须执行 import
命令,这是其中最 耗时 的事情(计算部分实际上更快)。
是否有解决方案让我只调用一次导入?我看了一下 Jython
- 可以写一个 class 或一些会被启动的东西,然后做一次导入,然后每次我想做计算部分时调用它的一个函数(fun
)?有没有人做过类似的事情或对此有任何其他解决方案?
第一次尝试实施
我试过写一个 'pipe' Java Class 来执行一次 python 脚本。现在脚本从 stdin 连续读取,当它获得输入 argument
时,它会进行计算并 returns 结果:
import sys
import special-library
def fun(x):
do something
print('END')
for arg in sys.stdin:
fun(arg)
当我从命令行测试它并为其提供输入参数时,这当然有效。
JavaClass如下:
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"))
知道这里出了什么问题吗?
您可以使用管道在 java 和 Python 之间进行通信。
你 运行 你的 Python 和现在一样(没有命令行参数)
Python 脚本
你在 python 中写了一个无限循环,它将
从 标准输入(它将是您的函数参数)
你调用你的函数
你把答案写到标准输出
Java
写一个发送参数到python
的方法
将函数的参数写入管道
从管道中读取答案
大功告成。
这是一些片段
这里是你如何创建你的管子
Process p = Runtime.getRuntime().exec(commande);
BufferedReader output = getOutput(p); //from python to java
BufferedReader error = getError(p); //from python to java
PrintWriter input = getInput(p); //from java to python
private static BufferedReader getOutput(Process p) {
return new BufferedReader(new InputStreamReader(p.getInputStream()));
}
private static BufferedReader getError(Process p) {
return new BufferedReader(new InputStreamReader(p.getErrorStream()));
}
private static PrintWriter getInput(Process p){
return new PrintWriter (new OutputStreamWriter(p.getOutputStream()));
}
在您的 Python 脚本中尝试以下操作:
import sys
def fun(x):
print(x)
print('END')
sys.stdout.flush()
while 1:
try:
line = sys.stdin.readline()
except KeyboardInterrupt:
break
if not line:
break
fun(line)
您的 Java 代码应该或多或少是正确的。