一、项目介绍:
本人在做一个java的spring-boot后端,这个后端需要接收一个文件,然后对这个文件进行一定的处理,随后返回给前端结果,这里的处理就是调用的写好的python程序。
针对我的情况,目前谷歌和百度没有一个涉及完整开发流程的教程,里面有很多的坑,我一点一点通过谷歌百度chatgpt填起来的。
数据的流动是:前端→springboot→python程序→springboot→前端
本文会介绍针对本地调试和服务器调试的案例。
二、环境配置:
2.1 java环境配置
我用的java 8,应该别的版本也可以,不需要额外的库
2.2 python环境配置
对于python的环境分两种情况:本地windows和服务器(一般为Linux或者centos)
对于python的输出,你需要打印到控制台上,也就是print出来,这样java才能捕捉到。
2.2.1 python+windows环境配置情况
就是正常的在windows上的python项目,能跑通就可以,没什么特殊的,建议使用虚拟环境而非全局环境。
2.2.2 python+linux环境配置情况
项目结构和windows的python项目一样,但是有一个地方不一样!那就是venv环境文件夹,这里的venv需要是linux的python环境。windows和linux的python环境结构是不同的。你需要根据python的版本,和你自己用到的库,自行安装环境。
后续的命令构建也会体现区别。
三、项目构建
3.1 核心语句:
//命令构建
List<String> command = getBuilderCommand(filteredData, filterMethod, peekMethod);
// 创建进程构建器
ProcessBuilder processBuilder = new ProcessBuilder(command);
if (!System.getProperty("os.name").toLowerCase().contains("win")) {
processBuilder.directory(new File("/www/wwwroot/SignalPlat/SignalPlatPY/SignalPlatPY_venv"));
}
// 错误输出流合并到标准输出流
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
InputStream inputStream = process.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder output = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
output.append(line);
}
int exitCode = process.waitFor();
if (exitCode == 0) {
return output.toString();
} else {
return "运行python脚本时出现问题,python错误输出为:" + output;
}
对于构建命令的方法,分两种操作系统:
public List<String> getBuilderCommand(String filteredData, String filterMethod, String peekMethod) throws IOException {
// 获取当前操作系统的名称
String osName = System.getProperty("os.name").toLowerCase();
// 设置配置信息
String pyVenv;
String pyScript;
// 构建命令参数列表
List<String> command = new ArrayList<>();
if (osName.contains("win")) {
command.add("cmd.exe");
command.add("/c");
pyVenv = "E:/project/PYsiglPlat/venv";
pyScript = "E:/project/PYsiglPlat/hrv.py";
command.add(pyVenv + "/Scripts/python.exe");
} else {
pyVenv = "/www/wwwroot/SignalPlat/SignalPlatPY/SignalPlatPY_venv/bin/python";
pyScript = "/www/wwwroot/SignalPlat/SignalPlatPY/hrv.py";
command.add(pyVenv);
}
// Python程序的路径
command.add(pyScript);
// python程序需要的参数们
command.add(filteredData);
command.add(filterMethod);
command.add(peekMethod);
return command;
}
内容有点多,下面一点点讲(如果你有chatgpt,你也可以用它读代码)
3.2 代码详解
1,首先,我们构建一条命令,这个命令是用来执行python程序的。不同操作系统下命令会有所不同。
我写了一个自定义函数getBuilderCommand(),该函数在上面有详细代码和详细注释。
//命令构建
List<String> command = getBuilderCommand(filteredData, filterMethod, peekMethod);
2,随后,我们执行这条命令
ProcessBuilder processBuilder = new ProcessBuilder(command);
3,值得一提的是,如果在linux环境下,我们需要加上一句
processBuilder.directory(new File("/www/wwwroot/SignalPlat/SignalPlatPY/SignalPlatPY_venv"));
需要指定他的python环境的工作目录。
4,如果输出流合并到标准输出流
// 错误输出流合并到标准输出流
processBuilder.redirectErrorStream(true);
就是python打印了啥java就捕捉啥。如果不加这句话,后续是会有两个输出流,一个是正确的,一个出错的,我没细研究,于是我让他俩合并了。个人感觉不加这句话更专业一些,可以分别处理是否python程序报错了的两种情况,你可以再研究研究。
5,随后就是开始执行,然后吧输出都捕捉到String output变量里,随后根据
int exitCode = process.waitFor();
exitCode来判断程序是否发生了错误,来采取不同的手段。
四,总结
个人感觉有几个关键点容易踩坑:
一是phthon项目在windows和linux上的结构是相似但是不同的。
二是两个操作系统上需要执行的命令是不同的。
三是你需要把python的结果打印到控制台,好让java捕捉到。
好了,你已经学会怎么使用java程序调用python程序了,有问题可以给我留言评论~peace