这里提供两种调用方法:
1、通过Jython来实现Java调用Python (目前只支持Python2)
2、通过ProcessBuilder来实现Java执行Python脚本(既支持Python2也支持Python3)
通过Jython来实现Java调用Python
Jython目前只支持Python2
一、准备好Python代码
下面是一个Python快排的代码:
def partition(arr, low, high):
i = low - 1
pivot = arr[high]
for j in range(low, high):
if arr[j] <= pivot:
i = i + 1
arr[i], arr[j] = arr[j], arr[i]
arr[i+1], arr[high] = arr[high], arr[i+1]
return i + 1
def quick_sort(arr, low, high):
if low < high:
p = partition(arr, low, high)
quick_sort(arr, low, p - 1)
quick_sort(arr, p + 1, high)
def do_sort(nums):
arr=nums
n=len(arr)
quick_sort(arr,0,n-1)
return arr
注意:如果加了中文记得注意中文乱码问题!!!
二、编写Springboot
1、引入依赖
这里只展示关键的依赖:Jpthon依赖
可以在这里找到相关依赖:https://mvnrepository.com/artifact/org.python/jython-standalone
<!-- https://mvnrepository.com/artifact/org.python/jython-standalone -->
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.3</version>
</dependency>
2、将Python代码放在指定目录
拿到他的绝对路径:
E:\\Java\\testDemo\\jython-demo\\src\\main\\java\\com\\bluefoxyu\\com\\bluefox\\py\\quick-sort.py
3、编写controller
在接口中用Java调用Python中的快排是实现排序
@RestController()
@RequestMapping("/py")
public class PyTestController {
@GetMapping("/jython/quick-sort")
public String PyTestQuickSort(){
PythonInterpreter interpreter=new PythonInterpreter();
List<Integer> list = new ArrayList<>();
Random random=new Random();
for (int i = 0; i < 10; i++) {
list.add(random.nextInt(100));
}
//使用interpreter.execfile方法执行一个Python脚本文件
interpreter.execfile("E:\\Java\\testDemo\\jython-demo\\src\\main\\java\\com\\bluefoxyu\\com\\bluefox\\py\\quick-sort.py");
//通过interpreter.get方法获取do_sort函数,并将其转换为PyFunction类型
PyFunction pyFunction = interpreter.get("do_sort", PyFunction.class);
//调用do_sort函数,将Java中的ArrayList转换为Jython的PyList,然后作为参数传递给Python函数
PyObject pyObject = pyFunction.__call__(new PyList(list));
return pyObject.toString();
}
}
注意:记得使用绝对路径,使用相对路径会报错。
4、postman中测试
测试通过!成功实现Java调用Python。
通过ProcessBuilder来实现Java执行Python脚本
支持Python2和Python3
下面讲述一下原理:
Java调用Python脚本的过程本质上是通过Java程序在底层操作系统上启动一个新进程来执行Python脚本。具体过程包括以下步骤:
- 进程启动:使用
ProcessBuilder
启动一个外部进程,在这个场景下是Python解释器。- 参数传递:将Java中生成的数据通过命令行参数的形式传递给Python脚本。
- 捕获输出:Python脚本执行后产生的输出通过标准输出流(
stdout
)返回,Java程序可以读取并处理这个输出。- 进程终止:等待Python脚本执行完毕后,Java程序获取进程的退出状态,并关闭所有相关资源。
一、修改之前的Python代码
下面是完整代码:
import json
import sys
def partition(arr, low, high):
i = low - 1
pivot = arr[high]
for j in range(low, high):
if arr[j] <= pivot:
i = i + 1
arr[i], arr[j] = arr[j], arr[i]
arr[i+1], arr[high] = arr[high], arr[i+1]
return i + 1
def quick_sort(arr, low, high):
if low < high:
p = partition(arr, low, high)
quick_sort(arr, low, p - 1)
quick_sort(arr, p + 1, high)
def do_sort(nums):
arr=nums
n=len(arr)
quick_sort(arr,0,n-1)
return arr
if __name__ == '__main__':
# 假设第一个命令行参数是JSON格式的列表
if len(sys.argv) > 1:
nums = json.loads(sys.argv[1])
print(do_sort(nums))
else:
print("Usage: python quick-sort.py <json_list>")
路径是:
E:\\Java\\testDemo\\jython-demo\\src\\main\\java\\com\\bluefoxyu\\com\\bluefox\\py\\quick-sort.py
二、编写Springboot
1、引入依赖
在案例中用到将数据转换成Json格式的数据传给Python脚本,这里用到的Json转化根据是hutool工具包里面的Json里面的JSONUtil,所以这里引入依赖:
<!--hutool工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.11</version>
</dependency>
2、编写controller
下面给出代码,代码里面都有解释:
@GetMapping("/io/quick-sort")
public String PyTestIoQuickSort() {
List<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 10; i++) {
list.add(random.nextInt(100));
}
// 使用Hutool库的JSONUtil.toJsonStr(list)方法将ArrayList转换为JSON格式的字符串,这样就能方便地将数据传递给Python脚本。
String jsonStr = JSONUtil.toJsonStr(list);
System.out.println("jsonStr = " + jsonStr);
/*BufferedReader reader :用于读取Python脚本的标准输出。
StringBuilder result :用于存储并拼接Python脚本的输出结果。*/
BufferedReader reader = null;
/*ProcessBuilder processBuilder:用于构建一个新的进程,以运行Python脚本。构造函数接受命令和参数:*/
StringBuilder result = new StringBuilder();
try {
ProcessBuilder processBuilder = new ProcessBuilder(
"python",
"E:\\Java\\testDemo\\jython-demo\\src\\main\\java\\com\\bluefoxyu\\com\\bluefox\\py\\quick-sort.py",
jsonStr);
/* 启动进程并运行Python脚本。*/
Process process = processBuilder.start();
/*reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
从Python脚本的标准输出流中读取数据。使用GBK编码格式读取,因为可能涉及到中文输出。*/
reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "gbk"));
String line;
// 逐行读取Python脚本的输出,并将其追加到result中。
while ((line = reader.readLine()) != null) {
result.append(line);
}
/*int exitCode = process.waitFor();:等待Python脚本执行完毕,并获取进程的退出状态码。
System.out.println("Exited with error code " + exitCode);:输出Python脚本的退出状态码,0表示成功执行。
System.out.println("Result: " + result.toString());:输出Python脚本的执行结果。*/
int exitCode = process.waitFor();
System.out.println("Exited with error code " + exitCode);
System.out.println("Result: " + result.toString());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
return "Error occurred: " + e.getMessage();
} finally {
//在finally块中关闭BufferedReader,以确保资源被正确释放。
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 返回Python脚本的输出结果
return result.toString();
}
这里给出ProcessBuilder processBuilder里面几个参数的解释:
"python"
:表示要启动的程序是Python解释器。"E:\\Java\\testDemo\\jython-demo\\src\\main\\java\\com\\bluefoxyu\\com\\bluefox\\py\\quick-sort.py"
:Python脚本的路径。jsonStr
:传递给Python脚本的参数,即JSON格式的整数列表。
3、postman中测试
IDEA中控制台输出:
说明成功实现Java调用Python!!
参考:
关于Java调用Python还可以参考一些博客:
在Java代码中使用Python_java集成python代码-CSDN博客
java调用python文件的几种方式【超细讲解!】_java_烟花苏柳-华为云开发者空间
java调用python文件的几种方式【超细讲解!】_java调用python方法-CSDN博客