一,说明
想实现如下功能,项目后端架构是Spring Boot,某个功能需要调用Python脚本来实现,调用Python脚本的功能要兼容Windows和Linux,即可以运行在Windows和Linux两种平台上。
二,Java代码
// 定义一个线程池来读取python脚本的执行结果
private static ExecutorService taskPool = new ThreadPoolExecutor(3, 10, 200L, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<>(200),new ThreadFactoryBuilder().setNamePrefix("thread-python-exec-runner-%d").build());private void execPythonFile(String path, String params) throws MoyaException {// 获得操作系统名称String os = System.getProperty("os.name");String[] args;if (os.startsWith("Windows")) {// 如果当前环境是Windows环境args = new String[]{"cmd.exe", "/c", "python", path, params};} else {// 如果当前环境是Linux环境args = new String[]{"python", path, params};}Process process = null;try {// 执行python脚本process = Runtime.getRuntime().exec(args);// 错误输出流InputStream errorStream = process.getErrorStream();// 正确输出流InputStream inputStream = process.getInputStream();// 开线程来读取执行失败的信息taskPool.submit(() -> {BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream));List<String> list = read(path, reader);log.info("Python Script execute failed, error message:{}", list);});// 开线程来读取执行成功的信息taskPool.submit(() -> {BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));List<String> list = read(path, reader);log.info("Python Script execute success, successful message:{}", list);});// 阻塞进程,等待执行完成int processResult = process.waitFor();if (processResult != 0) {log.error("Python Script error, waitFor is not zero.");throw new MoyaException("已知威胁流生成失败");}} catch (Exception e) {log.error("python script occur error:{}", e);throw new MoyaException("已知威胁流生成失败");} finally {try {// 在finally中关闭正确输出流与错误输出流process.getErrorStream().close();process.getInputStream().close();} catch (IOException e) {log.info("close process stream exception: {}", e);}// 执行完成,销毁Process对象process.destroy();}}
- 定义读取方法
/*** 读取输出流数据,并以数组形式返回读取结果** @param path 路径* @param reader 缓冲流对象* @return*/private List<String> read(String path, BufferedReader reader) {List<String> resultList = new ArrayList<>();String res = "";while (true) {try {// 读取到null值,跳出循环if ((res = reader.readLine()) == null) break;} catch (IOException e) {log.error("reading python file: {} occur exception: {}.", path, e);}// 将读取结果放入数组集合中resultList.add(res);}return resultList;}
三,Python代码
import sys# 定义一个主函数,作为脚本执行的入口,如果没有主函数,则从第一行开始执行
if __name__ == "__main__":# 获取外部输入参数param = sys.argv[1]print (param)