赞
踩
在工作业务中,需要实现用Java调用Python脚本,对比了网上主流的几种实现方式,最终选择以 Process的形式来实现业务需求。
- /**
- * 运行脚本文件
- *
- * @param scriptPath 脚本位置
- * @param params 请求参数
- */
- public void runScript(String scriptPath, List<String> params) {
- long start = System.currentTimeMillis();
- long end = 0L;
- try {
- ProcessBuilder processBuilder = new ProcessBuilder();
- processBuilder.redirectErrorStream(true);
- List<String> commands = new ArrayList<>();
- commands.add("python");
- commands.add(scriptPath);
-
- // 参数编码
- log.info("runScript params:" + params);
- params = encodeParams(params);
- commands.addAll(params);
- // 加载命令
- processBuilder.command(commands);
- // 启动进程
- Process process = processBuilder.start();
- String result = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))
- .lines().collect(Collectors.joining());
- log.info("runScript result:" + result);
- Long end = System.currentTimeMillis();
- process.waitFor();
- } catch (Exception e) {
- log.info("运行脚本文件失败:" + e.getMessage());
- Long end = System.currentTimeMillis();
- }
- log.info("运行时间:" + (end - start));
- }
-
- /**
- * 参数编码
- *
- * @param params 参数
- * @return 编码后的参数
- */
- private List<String> encodeParams(List<String> params) {
- if (params == null || params.isEmpty()) {
- return params;
- }
- List<String> list = new ArrayList<>();
- for (String param : params) {
- param = param.replace("\"", "@");
- param = new String(param.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
- list.add(param);
- }
- return list;
- }
此处参数编码是特殊处理,需要根据实际业务来处理。Java以Process形式实现的就是类似于CMD窗口运行程序,传递的参数是不能有引号的,如果参数比较简单可以省去这一步,如果需要传递JSON等类型的长字符串,那么需要将引号转为其它符号或者字符串,而且需要和Python端约定好,此处我使用了@符号替换了引号。
python返回的参数是python程序执行完成后返回给Java段,返回形式是以窗口输出流的形式返回,也就是在python中使用 print() 或者使用log输出等都会返回给Java。
- sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
-
- if __name__ == '__main__':
- # 获取Java传递过来的参数,参数是一个列表,第一个是文件位置。后续都是传递过来的参数
- argv = sys.argv
- data = argv[1]
- data = data.replace('@', '"')
- result = json.loads(data)
- print("此处是一个打印。" + str(result))
Java调用Pyhton脚本,一个最主要的问题就是需要处理编码问题,此处我统一使用 UTF-8形式处理。
Java中编码处理如下:
写出编码:
param = new String(param.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
读取编码:
String result = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8)).lines().collect(Collectors.joining());
Python中编码处理如下:
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。