项目需求:需要java调用python脚本,而且需要向脚本中传递参数,经过很长时间的摸索之后研究出了点东西,因为实在没有老师教,所以只能摸索出了最笨的方法,现在记录下来,希望大家有好的方法多多指教。
1、执行单行代码,使用Jython
org.python
jython-standalone
2.7.1
/**
* 执行单行代码
*/
@Test
public void test1_code(){
PythonInterpreter pythonInterpreter=new PythonInterpreter();
pythonInterpreter.exec("print('-----执行单行代码:Hello')");
}
2、执行文件脚本,有函数名不带参数,而且不引用三方库,使用Jython
hello.py:
def hello():
return '----py文件执行结果:Hello'
/**
* 执行文件脚本,有函数名不带参数,不使用三方库
*/
@Test
public void test2_file(){
PythonInterpreter pythonInterpreter=new PythonInterpreter();
//注意这边要用绝对路径
pythonInterpreter.execfile("E:\\mlthfs\\src\\main\\resources\\pythonDemo\\hello.py");
//第一个参数为期望获得的函数(变量)的名字,第二个参数为期望返回的对象类型
PyFunction pyFunction=pythonInterpreter.get("hello",PyFunction.class);
//调用函数,此时call无参数
PyObject pyObject=pyFunction.__call__();
System.out.println(pyObject);
}
3、执行文件脚本,由函数名,带参数,不用三方库,Jython
testWithParam.py:
def my_test(name, age):
print("name: "+name)
print("age: "+age)
return "success"
/**
* 执行文件脚本,由函数名,带参数
*/
@Test
public void test3_Param(){
PythonInterpreter interpreter=new PythonInterpreter();
interpreter.execfile("E:\\mlthfs\\src\\main\\resources\\pythonDemo\\testWithParam.py");
PyFunction pyFunction=interpreter.get("my_test",PyFunction.class);
//调用函数,此时call传入两个参数
PyObject pyObject=pyFunction.__call__(new PyString("tom"),new PyString("25"));
System.out.println(pyObject.toString());
}
4、调用脚本,使用三方库,传递参数list,脚本接收一维数组,
说明一下,python脚本中需要接收两个一维数组作为数据输入,我的思路是从java中传入list,然后再在ppython中做处理将传进去的参数转为数组,进行运算。
传参数的时候只能将所有的参数组合成一个字符串,实质是cmd命令行。
接收的时候使用sys.argv方法接收脚本外传入的参数,并且组成一个列表list,第一个元素是命令行,从第二个开始就是传入的list参数,使用print(sys.argv[1:])打印出来就是:
sys.argv[1:]== ['[3340,', '4525,', '7304,', '3335,', '5319,', '5319,', '3932,', '3932,', '4]']
现在看来格式很乱。需要根据需要处理:具体在脚本中体现,不一一赘述。
Process process = Runtime.getRuntime().exec(
pythonPath + filePath + list1);
public void test6_ThirdPackage_param() {
String pythonPath="D:\\Program Files\\Python\\Python36\\python.exe ";
String filePath="E:\\mlthfs\\src\\main\\resources\\pythonDemo\\test7.py ";
//首先定义两个list,赋值。
List list1 = new ArrayList<>();
List list2 = new ArrayList<>();
Integer list1Size=null;
//给list1赋值
list1.add(3340);
list1.add(4525);
list1.add(7304);
list1.add(3335);
//给list2赋值
list2.add(5319);
list2.add(5319);
list2.add(3932);
list2.add(3932);
//得到第一个list的size,传入脚本中,方便分割参数
list1Size=list1.size();
System.out.println("list1-size()"+list1.size());
//将list1.list2合并
list1.addAll(list2);
//将size加到list1最后
list1.add(list1Size);
try {
Process process = Runtime.getRuntime().exec(
pythonPath + filePath + list1);
BufferedReader in=new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line=in.readLine())!=null){
System.out.println(line);
}
in.close();
int re=process.waitFor();
System.out.println(re==1?"----状态码1----运行失败":"----状态码0----运行成功");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
py脚本:
import sys
# 评估指标
def MetricsValue(yobs,yfit):
import numpy as np
yyobs=np.array(yobs)
yyfit=np.array(yfit)
data =[yyobs, yyfit]
R=np.corrcoef(data) [0,1] # 相关系数
# 预报的变幅误差
yo_yp=yyfit-yyobs
BFWC=yo_yp/np.ptp(yyobs)
V10 = np.size(np.where((abs(BFWC) <= 0.1)))/np.size(yyobs) # 非常要注意这个括号 没有括号估计内部执行顺序不对
V20 = np.size(np.where((abs(BFWC) <=0.2))) / np.size(yyobs)
# 确定性系数
D1=np.sum(yo_yp**2)
D2=np.sum((yyobs-np.mean(yyobs))**2)
D=1-D1/D2
#均方根误差RMSe
Rmse1=sum(yo_yp**2)
Rmse=np.sqrt(Rmse1/np.size(yyobs))
print("R",R)
return R,V10,V20,D,Rmse
if __name__ == '__main__':
print("=============start-------------")
#存放所有的参数 最后一个为第一个列表的长度(分割时用)
list_str = []
#存放字符型list
list1_str=[]
list2_str=[]
#字符型转换为int型
list_int=[]
list1_int=[]
list2_int=[]
print("len(sys.argv[1:])==",len(sys.argv[1:]))
print("sys.argv[1:]==",sys.argv[1:])
for i in range(1, len(sys.argv)):
list_str.append(sys.argv[i].replace(",", ""))
print("list_str[0]==",list_str[0])
print("len(list_str)==",len(list_str))
#处理第一个还有最后一个元素的格式
list_str[0] = list_str[0].replace("[", "")
list_str[len(sys.argv)-2] = list_str[len(sys.argv)-2].replace("]", "")
print("=before===String-list===list_str",list_str)
#取出最后一个数作为第一个列表的长度来分割列表
list1Size=int(list_str[len(list_str)-1])
print("list1Size==",list1Size)
#根据size取出第一个列表list[a:b]表示取出下表为a到下标为b-1的值组成一个list
list1_str=list_str[0:list1Size]
print("list1_str==",list1_str)
#取出第二个列表
list2_str=list_str[list1Size:len(list_str)-1]
print("list2_str==",list2_str)
#将str转换为int
list_int=list(map(int, list_str))
list1_int=list(map(int, list1_str))
list2_int=list(map(int, list2_str))
print("list_int==",list_int)
print("list1_int==",list1_int)
print("list2_int==",list2_int)
print(MetricsValue(list1_int,list2_int))
print("-------------end===============")
最终控制台打印结果:
list1-size()4
=============start-------------
len(sys.argv[1:])== 9
sys.argv[1:]== ['[3340,', '4525,', '7304,', '3335,', '5319,', '5319,', '3932,', '3932,', '4]']
list_str[0]== [3340
len(list_str)== 9
=before===String-list===list_str ['3340', '4525', '7304', '3335', '5319', '5319', '3932', '3932', '4']
list1Size== 4
list1_str== ['3340', '4525', '7304', '3335']
list2_str== ['5319', '5319', '3932', '3932']
list_int== [3340, 4525, 7304, 3335, 5319, 5319, 3932, 3932, 4]
list1_int== [3340, 4525, 7304, 3335]
list2_int== [5319, 5319, 3932, 3932]
R -0.4279893568893351
(-0.4279893568893351, 0.0, 0.25, -0.5495247640483161, 2017.0318539874377)
-------------end===============
----状态码0----运行成功
5、调用脚本,使用三方库,传递参数list,脚本接收二维数组
这一种跟上一步的过程类似,不同点就是脚本需要的参数是二维数组,直接上代码
/**
* 接收二维数组
*
*/
@Test
public void test7_ThirdPackage_param() {
String pythonPath="D:\\Program Files\\Python\\Python36\\python.exe ";
String filePath="E:\\mlthfs\\src\\main\\resources\\pythonDemo\\test8.py ";
Integer x_count=null;//因子个数
Integer year_count=null;//年数
List newList=new ArrayList<>();
List list1=new ArrayList<>();
list1.add(328);
list1.add(941);
list1.add(385);
list1.add(4327);
x_count=list1.size();
year_count=4;//假设为4年
List list2 = new ArrayList<>();
//给list2赋值
list2.add(388);
list2.add(1529);
list2.add(2063);
list2.add(4108);
List list3 = new ArrayList<>();
list3.add(436);
list3.add(891);
list3.add(1719);
list3.add(4272);
List list4 = new ArrayList<>();
list4.add(467);
list4.add(2450);
list4.add(1148);
list4.add(1382);
List list5 = new ArrayList<>();
list4.add(3340);
list4.add(4525);
list4.add(7304);
list4.add(3335);
System.out.println("newList0"+newList);
newList.addAll(list1);
System.out.println("newList1"+newList);
newList.addAll(list2);
System.out.println("newList2"+newList);
newList.addAll(list3);
newList.addAll(list4);
System.out.println("newList4"+newList);
newList.addAll(list5);
newList.add(x_count);
newList.add(year_count);
System.out.println(newList);
try {
Process process = Runtime.getRuntime().exec(
pythonPath + filePath +newList);
BufferedReader in=new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line=in.readLine())!=null){
System.out.println(line);
}
in.close();
int re=process.waitFor();
System.out.println(re==1?"----状态码1----运行失败":"----状态码0----运行成功");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
py脚本:
# -*- coding:utf-8 -*-
import sys
import numpy as np
# 评估指标
def MetricsValue(yobs,yfit):
import numpy as np
yyobs=np.array(yobs)
yyfit=np.array(yfit)
data =[yyobs, yyfit]
R=np.corrcoef(data) [0,1] # 相关系数
# 预报的变幅误差
yo_yp=yyfit-yyobs
BFWC=yo_yp/np.ptp(yyobs)
V10 = np.size(np.where((abs(BFWC) <= 0.1)))/np.size(yyobs) # 非常要注意这个括号 没有括号估计内部执行顺序不对
V20 = np.size(np.where((abs(BFWC) <=0.2))) / np.size(yyobs)
# 确定性系数
D1=np.sum(yo_yp**2)
D2=np.sum((yyobs-np.mean(yyobs))**2)
D=1-D1/D2
#均方根误差RMSe
Rmse1=sum(yo_yp**2)
Rmse=np.sqrt(Rmse1/np.size(yyobs))
print("R",R)
return R,V10,V20,D,Rmse
# 拟合
def SVRFit (Obsx,Obsy):
from sklearn.svm import SVR
import numpy as np
from sklearn.model_selection import cross_val_predict
print("obsx",Obsx)
print("obsy",Obsy)
xobs=np.array(Obsx)
yobs=np.array(Obsy)
modelFit=SVR(kernel='rbf', C=1e3, gamma=0.1)
yfit = cross_val_predict(modelFit, xobs, yobs, cv=2)# 交叉验证返回对应的拟合值,根据Obsy和yfit计算评估指标
MetrValue=MetricsValue(yobs,yfit)
modelFit.fit(xobs,yobs)
print('MetrValue', MetrValue)
print('yfit', yfit)
return MetrValue, yfit
if __name__ == '__main__':
print("=============start-------------")
# 存放所有的参数 最后一个为第一个列表的长度(分割时用)
list_str = []
# 存放字符型list
list1_str = []
list2_str = []
# 字符型转换为int型
list_int = []
list1_int = []
list2_int = []
# 存放转换出来的二维数组
list1_int2 = []
print("len(sys.argv[1:])==", len(sys.argv[1:]))
print("sys.argv[1:]==", sys.argv[1:])
for i in range(1, len(sys.argv)):
list_str.append(sys.argv[i].replace(",", ""))
print("list_str[0]==", list_str[0])
print("len(list_str)==", len(list_str))
# 处理第一个还有最后一个元素的格式
list_str[0] = list_str[0].replace("[", "")
list_str[len(sys.argv) - 2] = list_str[len(sys.argv) - 2].replace("]", "")
print("=before===String-list===list_str", list_str)
# 年数(行数)
year_count = int(list_str[len(list_str) - 1])
# 因子个数(列数)
x_count = int(list_str[len(list_str) - 2])
print("year_count=行数=", year_count)
print("x_count=列数=", x_count)
# 第一个数组
list1_str = list_str[0:int(year_count * x_count)]
print("list1", list1_str)
list1_int = list(map(int, list1_str))
print("list1_int", list1_int)
# 使用numpy库的函数将一维数组转换为二维
list1_int2 = np.array(list1_int).reshape((year_count, x_count))
print("list1_int2", list1_int2)
# 第二个数组
list2_str = list_str[int(year_count * x_count):len(list_str) - 2]
print("list2_str", list2_str)
list2_int = list(map(int, list2_str))
print("list2_int", list2_int)
print("-------------result:===============")
print("list1_int2", list1_int2)
print("list2_int", list2_int)
print(SVRFit(list1_int2,list2_int))
print("-------------end===============")
运行结果:
=============start-------------
len(sys.argv[1:])== 22
sys.argv[1:]== ['[328,', '941,', '385,', '4327,', '388,', '1529,', '2063,', '4108,', '436,', '891,', '1719,', '4272,', '467,', '2450,', '1148,', '1382,', '3340,', '4525,', '7304,', '3335,', '4,', '4]']
list_str[0]== [328
len(list_str)== 22
=before===String-list===list_str ['328', '941', '385', '4327', '388', '1529', '2063', '4108', '436', '891', '1719', '4272', '467', '2450', '1148', '1382', '3340', '4525', '7304', '3335', '4', '4']
year_count=����= 4
x_count=����= 4
list1 ['328', '941', '385', '4327', '388', '1529', '2063', '4108', '436', '891', '1719', '4272', '467', '2450', '1148', '1382']
list1_int [328, 941, 385, 4327, 388, 1529, 2063, 4108, 436, 891, 1719, 4272, 467, 2450, 1148, 1382]
list1_int2 [[ 328 941 385 4327]
[ 388 1529 2063 4108]
[ 436 891 1719 4272]
[ 467 2450 1148 1382]]
list2_str ['3340', '4525', '7304', '3335']
list2_int [3340, 4525, 7304, 3335]
-------------result:===============
list1_int2 [[ 328 941 385 4327]
[ 388 1529 2063 4108]
[ 436 891 1719 4272]
[ 467 2450 1148 1382]]
list2_int [3340, 4525, 7304, 3335]
obsx [[ 328 941 385 4327]
[ 388 1529 2063 4108]
[ 436 891 1719 4272]
[ 467 2450 1148 1382]]
obsy [3340, 4525, 7304, 3335]
R -0.4279893568893351
MetrValue (-0.4279893568893351, 0.0, 0.25, -0.54952466883164, 2017.0317920151879)
yfit [5319.5 5319.5 3932.5 3932.5]
((-0.4279893568893351, 0.0, 0.25, -0.54952466883164, 2017.0317920151879), array([5319.5, 5319.5, 3932.5, 3932.5]))
-------------end===============
----状态码0----运行成功