Java调用python脚本方法

java调用python脚本方法

今天项目中需要用到一个python脚本,将python脚本写完之后,忽然接到消息需要集成的java项目中,然后写了一个在java项目里面调用python脚本的代码,话不多说,直接上代码


import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;

@Slf4j
public class PyUtil {

    // 最大等待时间(秒),避免无限期卡住
    private static final int MAX_WAIT_SECONDS = 60;

    public static String executePythonScript(String[] args) {
        Process process = null;
        ExecutorService executor = Executors.newFixedThreadPool(2);
        AtomicReference<String> result = new AtomicReference<>("成功");
        try {
            // 构建命令行参数
            String osName = System.getProperty("os.name").toLowerCase();
            if (osName.contains("linux")) {
                args[0] = "python3";
            } else if (osName.contains("windows")) {
                args[0] = "python";
            }

            log.info("正在执行 Python 脚本: {}", String.join(" ", args));

            ProcessBuilder pb = new ProcessBuilder(args);
            pb.redirectErrorStream(false); // 不合并 stderr 和 stdout
            process = pb.start();

            Charset charset = getCharsetForCurrentOs();

            // 启动线程读取标准输出
            Process finalProcess = process;
            Future<?> stdoutFuture = executor.submit(() -> readStream(finalProcess.getInputStream(), charset, false));
            // 启动线程读取错误输出
            Future<?> stderrFuture = executor.submit(() -> readStream(finalProcess.getErrorStream(), charset, true));

            // 等待进程结束或超时
            boolean exited = process.waitFor(MAX_WAIT_SECONDS, TimeUnit.SECONDS);
            if (!exited) {
                log.error("Python 脚本执行超时,强制终止进程");
                process.destroyForcibly();
                result.set("失败: 执行超时");
            } else {
                int exitCode = process.exitValue();
                if (exitCode != 0) {
                    result.set("失败: 退出码=" + exitCode);
                }
            }
            // 确保两个线程完成
            stdoutFuture.get(1, TimeUnit.SECONDS);
            stderrFuture.get(1, TimeUnit.SECONDS);
            return result.get();
        } catch (IOException e) {
            log.error("执行 Python 脚本失败: IO 异常", e);
            result.set("失败: IO 异常 - " + e.getMessage());
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            log.error("执行 Python 脚本失败: 中断或超时", e);
            result.set("失败: 中断或超时 - " + e.getMessage());
            if (process != null) {
                process.destroyForcibly();
            }
        } finally {
            if (process != null) {
                process.destroy(); // 确保进程被销毁
            }
            executor.shutdownNow(); // 关闭线程池
        }
        return result.get();
    }

    /**
     * 获取当前操作系统对应的字符集
     */
    private static Charset getCharsetForCurrentOs() {
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("windows")) {
            return Charset.forName("GBK"); // Windows 下使用 GBK 防止乱码
        }
        return Charset.defaultCharset();
    }

    /**
     * 读取并打印输入流内容
     */
    private static void readStream(InputStream inputStream, Charset charset, boolean isError) {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charset))) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (isError) {
                    log.error("PYTHON-ERR: {}", line);
                } else {
                    log.info("PYTHON-OUT: {}", line);
                }
            }
        } catch (IOException e) {
            log.error("读取流失败", e);
        }
    }
}

demo调用

public static void main(String[] args) {
        try {

            String path = System.getProperty("user.dir");

            String[] params = new String[]{
                    "python3",
                    path + "/python/your_script.py",
                    "arg1",
                    "arg2",
                    "1" // 1:数据库操作,2:csv/excel文档操作
            };
            PyUtil.executePythonScript(params);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }```

你可能感兴趣的:(java,python,开发语言)