• Java程序中调用Python脚本(兼容Windows与Linux)


    一,说明

    想实现如下功能,项目后端架构是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();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 定义读取方法
    /**
         * 读取输出流数据,并以数组形式返回读取结果
         *
         * @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;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    三,Python代码

    import sys
    #sys.path.append(os.path.join('/opt/test/demo'))
    
    # 定义一个主函数,作为脚本执行的入口,如果没有主函数,则从第一行开始执行
    if __name__ == "__main__":
        # 获取外部输入参数
        param = sys.argv[1]
        print (param)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    leetcode每天5题-Day01
    Kafka三种认证模式,Kafka 安全认证及权限控制详细配置与搭建
    如何设计一个优惠券系统
    LeetCode //C - 103. Binary Tree Zigzag Level Order Traversal
    Prim 求 MST| INIT: cost[][]耗费矩阵(inf为无穷大);
    CentOS服务器利用docker搭建中间件命令集合
    应用案例|基于三维机器视觉的曲轴自动化上下料应用方案
    【Java设计模式 规范与重构】 六 代码重构小结
    Springboot毕业设计毕设作品,个人博客系统设计与实现
    音频频谱动画的原理与实现(一)
  • 原文地址:https://blog.csdn.net/weixin_44924882/article/details/133563427