JAVA调用python

该博客介绍了如何在Java中通过Runtime.getRuntime().exec()方法执行Python脚本,并利用回调函数实时处理Python运行过程中的输出信息。内容包括构建命令行字符串,解析Python的打印输出,以及定义回调函数来处理模型运行状态。示例展示了如何在运行结束时进行最终回调,以判断运行是否成功。

使用的方法是Runtime.getRuntime().exec(命令行),下面是项目里用来生成命令行的方法

// 生成脚本命令
private String buildModelCMD() {
    // 业务代码,略过

    // conda环境名称 + python程序路径 + 各种参数
    String cmd = String.format("CMD /C activate %s && python -u %s %s %s",/*参数已省略*/);
    // 替换转义字符
    cmd = cmd.replaceAll("\\\\", "/");
    cmd = cmd.replaceAll("/r", "\\\\r");
    cmd = cmd.replaceAll("/n", "\\\\n");
    cmd = cmd.replaceAll("/c", "\\\\c");
    return cmd;
}

下面是模型运行工具,使用function回调处理python实时打印的信息,modelruninfo是和python约定的输出格式

/**
 * python模型运行工具
 */
public class PythonRunnerUtil {

    /**
     * 运行python命令
     *
     * @param globalScript  命令行
     * @param callback      回调函数,参数为ModelResult类型
     * @param finalCallBack 最终的回调,参数1有问题 0正常
     */
    public static void runPython(
        String globalScript,
        Function<Object, ModelRunInfo> callback,
        Function<Object, Integer> finalCallBack
    ) {

        try {

            Process process = Runtime.getRuntime().exec(globalScript);

            // 读取运行过程输出信息
            Thread thread = printMessage(
                process.getInputStream(),
                process.getErrorStream(),
                (Object result) -> {
                    callback.apply(result);
                    return result;
                }
            );

            thread.join();

            finalCallBack.apply(process.waitFor()); // 1有问题 0正常
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 运行python,打印运行状态
     *
     * @param out      输出流
     * @param err      错误流
     * @param callback 运行中的回调
     * @return Thread
     */
    private static Thread printMessage(
        final InputStream out,
        final InputStream err,
        Function<Object, Object> callback
    ) {

        Thread thread = new Thread(() -> {

            Reader outReader = new InputStreamReader(out);
            BufferedReader outBf = new BufferedReader(outReader);

            Reader errReader = new InputStreamReader(err);
            BufferedReader errBf = new BufferedReader(errReader);

            String outLine, errLine = null;
            ModelRunInfo modelRunInfo = null;

            try {
                while (
                    (outLine = outBf.readLine()) != null
                    ||
                    (errLine = errBf.readLine()) != null
                ) {

                    System.out.println("python print outline >> " + outLine);

                    if (outLine != null) {
                        modelRunInfo = parsePrint(outLine);
                    }
                    if (errLine != null) {
                        modelRunInfo = new ModelRunInfo("error", -1, errLine);
                    }
                    if (modelRunInfo != null) {
                        // 运行中的回调
                        callback.apply(modelRunInfo);
                    }
                }

                outBf.close();
                errBf.close();
            } catch (IOException e) {

                modelRunInfo = new ModelRunInfo("error", -1, e.toString());
                callback.apply(modelRunInfo);
            } finally {

                try {
                    outBf.close();
                    errBf.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        
        thread.start();
        return thread;
    }

    /**
     * 将python打印输出的信息过滤后存为ModelRunInfo格式
     *
     * @param out 输出的字符串
     * @return ModelRunInfo
     */
    private static ModelRunInfo parsePrint(String out) {

        if (!out.startsWith("$JAVA$")) {
            return null;
        }

        out = out.replaceAll("\\$JAVA\\$", "");
        return JSON.parseObject(out, ModelRunInfo.class);
    }
}

/**
 * python运行的打印输出格式
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ModelRunInfo {
    String status;
    int progress;
    String jsonPath;
    // json输出文件里file和data的key
    public static final String FILE_KEY = "file";
    public static final String DATA_KEY = "data";
}

调用的示例

PythonRunnerUtil.runPython(cmd, (Object result) -> {
    ModelRunInfo modelRunInfo = (ModelRunInfo) result;
    log.info("model print >> " + modelRunInfo.toString());

    if (modelRunInfo.getProgress() == 100 && !modelRunInfo.getStatus().equals("error")) {
        // 具体业务
    }
    return (ModelRunInfo) result;
}, (Object finalResult) -> {
    int res = (Integer) finalResult;
    log.info("model end at >> " + DateTime.now().toString() + " with status " + res);
    return res;
});
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值