通过Java运行Python脚本,只导入一次
2020年4月更新:我接受了下面的答案,因为它为我的问题提供了一个非常好且简单的解决方案,但我的代码从未运行过!如果有人已经建立了类似的东西,请与我联系通过Java运行Python脚本,只导入一次,java,python,import,jython,Java,Python,Import,Jython,2020年4月更新:我接受了下面的答案,因为它为我的问题提供了一个非常好且简单的解决方案,但我的代码从未运行过!如果有人已经建立了类似的东西,请与我联系 我有一个简单的脚本my script.py,它使用Python编写的特定库快速执行一些计算: 导入系统 导入专用库 def fun(x): 做点什么 乐趣(sys.argv[1]) 在我的Java代码中,我使用ProcessBuilder方法在代码的不同部分大量使用/调用此脚本,这意味着我只需运行命令python my-script.py参
我有一个简单的脚本
my script.py
,它使用Python
编写的特定库快速执行一些计算:
导入系统
导入专用库
def fun(x):
做点什么
乐趣(sys.argv[1])
在我的Java
代码中,我使用ProcessBuilder
方法在代码的不同部分大量使用/调用此脚本,这意味着我只需运行命令python my-script.py参数
。
这意味着每次调用此脚本时,我都必须执行import
命令,这是其中最耗时的命令(计算部分实际上更快)
是否有一个解决方案以便我只调用导入一次?我看了一点关于Jython
-是否可以编写一个类或什么东西,启动导入一次,然后每次我想做计算部分时调用它的函数(fun
)?有没有人做过类似的事情或有其他解决方法
实施的第一次尝试
我试图编写一个“pipe”Java类,它将执行python脚本一次。现在,脚本不断地从stdin读取数据,当它获得一个输入参数时,它进行计算并返回结果:
导入系统
导入专用库
def fun(x):
做点什么
打印('结束')
对于sys.stdin中的arg:
乐趣(arg)
当然,当我从命令行测试它并为它提供输入参数时,这是有效的
Java类如下所示:
package my.package;
导入java.io.*;
公共级蟒蛇钳{
私有静态缓冲阅读器pythonToJavaReader;
私有静态PrintWriter javaToPythonWriter;
公共PythonScriptExecuter()引发异常{
字符串MPBNScriptFile=“fullPathToScriptFile”;
ProcessBuilder pb=新的ProcessBuilder(“python”,MPBNScriptFile);
pb.重定向错误流(真);
//开始脚本
进程p=pb.start();
pythonToJavaReader=getOutputReader(p);//从python到java
javaToPythonWriter=getInputWriter(p);//从java到python
}
//Python=>Java
私有静态BufferedReader getOutputReader(进程p){
返回新的BufferedReader(新的InputStreamReader(p.getInputStream());
}
//Java=>Python
私有静态PrintWriter getInputWriter(进程p){
返回新的PrintWriter(新的OutputStreamWriter(p.getOutputStream());
}
公共静态Arraylist getResults(字符串参数)引发IOException{
//将参数发送到python脚本
println(参数);
//javaToPythonWriter.flush();
//一个接一个地把结果拿回来
ArrayList结果=新建ArrayList();
整数计数=0;
弦线;
而(!(line=pythonToJavaReader.readLine()).equals(“END”)){
//进程'line'字符串
结果:添加(行);
}
返回结果;
}
}
因此,我要做的是,在代码的初始化部分,我有一行简单的代码来启动这个过程:
新的MPBNPythonScriptExecuter();
稍后,当我想得到一些结果时,我会使用:
String arg = "something"
Arraylist<String> res = PythonScriptExecuter.getResults(arg);
您知道这里出了什么问题吗?您可以使用管道在java和Python之间进行通信 您可以像现在一样运行Python(没有命令行参数) Python脚本 用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代码应该或多或少是正确的。这听起来很有希望!我会在这个基础上制定一个解决方案,然后再回来找你!您还将避免.exec(),它将只执行一次,就像importt在这种情况下,脚本的此函数不能有并行请求,对吗?例如,两个进程同时调用函数(同一进程的
p
),由于脚本写入stdout
,您不知道哪些结果将属于哪个。也许Java中的synchronized
在这种情况下会有所帮助,will check.Hi Pascal!我遇到了一个问题,用我目前的方法编辑了这个问题。如果可能的话,你能检查一下吗?如果你需要一个并行调用,那么最好采用客户机/服务器的方法,但我认为这对于你的需要来说会非常复杂。使用IO管道的解决方案是一种顺序解决方案,您需要确保其安全并将同步添加到getResults方法中。您是否验证了python脚本没有错误?还需要用类似这样的东西捕获错误,而((ligne=error.readLine())!=null){System.out.println(“err:+ligne”);}不,更像是它在某种程度上没有正确读取(可能在正确的时间)。。。当我杀死java程序时,有时我可以在while循环中看到输出(我打印行
)-但只有在那时-就像它被卡住了一样…谢谢你的努力!这个问题仍然存在,我认为主要与Java部分有关。
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)