在项目中遇到通过Java来调用python脚本,训练模型的场景,我对python没有什么过多的了解,就看过一点python脚本,和在windows中安装了下python环境和一个IDE。于是搜索一番记录一下。
- 第一步就是安装python环境,这个就直接百度吧。。。和一个python脚本,这里要注意python脚本和环境的版本应该一致,因为python2.x和python3.x兼容性不是很好。
- java中调用python,一般有两种方式:
1. Jython
Jython是一门语言,并非是Java 或者Python的解释器.用它可以实现,java和python代码的互相访问。使用时需要在pom中引入Jython的依赖,然后就可以在Java代码中直接使用python语法了。但是这种不是我需要的方式,而且经常不错,所以放弃了这种方式。
2. java.lang.Runtime
直接使用java自带的Runtime,这种方式不需要引入外部依赖,而且很好用。直接使用Runtime.getRuntime().exec(args),然后采用输出流的方式用来获取参数就可以了。
如果不需要向python中传递参数,则python脚本和java代码如下(值得注意的是,执行py命令时,前面要加 python!):
package com.caxs.warn;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @Author: TheBigBlue
* @Description:
* @Date: 2019/9/25
*/
public class Test {
public static void main(String[] args) {
BufferedReader br = null;
String temp;
StringBuilder sb = new StringBuilder();
try {
Process process = Runtime.getRuntime().exec("python D:\\Download\\exe_script.py");
br = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((temp = br.readLine()) != null) {
sb.append(temp);
}
System.out.println(sb.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
if(br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
import numpy as np
a = np.arange(12).reshape(3,4)
print(a)
如果需要向python中传递参数,则python脚本和java代码如下(值得注意的是,执行py命令时,前面要加 python!):
public static void main(String[] args) {
BufferedReader br = null;
String temp;
StringBuilder sb = new StringBuilder();
try {
//需传入的参数
String a = "car", b = "D3455054", c = "LJ12GKS28D4418248", d = "qingdao";
//设置命令行传入参数
String[] arr = new String[] { "python", "D:\\Download\\test.py", a, b, c, d };
Process process = Runtime.getRuntime().exec(arr);
//读取正常结果
BufferedReader inBr = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));
//读取异常结果
BufferedReader errBr = new BufferedReader(new InputStreamReader(process.getErrorStream(), "GBK"));
String lineStr;
while ((lineStr = inBr.readLine()) != null) {
System.out.println(lineStr);
}
while ((lineStr = errBr.readLine()) != null) {
System.err.println(lineStr);
}
process.waitFor();
inBr.close();
errBr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
import sys
print ("脚本名:", sys.argv[0])
for i in range(1, len(sys.argv)):
print ("参数", i, sys.argv[i])
问题
在测试向python传参的时候,总是没有返回结果,当时是没有获取errInputStream的。
打开errInputStream才发现问题。
这就是python环境是3.x而脚本却是2.x的语法,所以修改了python脚本,然后当时没有指定字符集,就出现了下面的情况:
BufferedReader inBr = new BufferedReader(new InputStreamReader(process.getInputStream()));
这是在java调用python乱码了,所以需要在new BufferedReader时指定字符集,因为是在windows环境的cmd下运行的python,cmd默认编码是gbk,所以指定gbk编码恢复正常。
BufferedReader inBr = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));