Java 运行python程序

最近在做一个研究,因为需要使用机器学习的方法而使用了python,而模型的验证我选择了一个开源库,但是这个开源库是采用java编写的。因此需要在验证的时候使用java调用python才行。
通过查找发现,java调用python其实并不困难,网上有很多方法实现。但是我的情况比较特殊,不能够简单地采取其中的任意一条,通过相关的搜索,我综合了几个方法完成了我的python调用器。

基本原理

采用 Runtime.getRuntime() 的方法运行python脚本,通过在python文件中调用 print() 函数来返回结果。

可能存在的问题
  • 不是默认的python环境。找到对应环境的路径,修改命令的参数即可。Runtime.getRuntime(“python”, path)Runtime.getRuntime(“xxx/xxx/python.exe”, path)
  • 调用了其它文件夹下的包。这种情况下,直接采用命令台运行会报错。基本原理是针对python脚本做修改,在开头添加sys.path.append(root)这样一句即可(root 表示项目的根文件夹,加入这个可以调用该文件夹下所有包)。为了将这个修改在java程序中完成,我设计了一个缓存机制,先读取目标代码,在读取结果的开头加入import syssys.path.append(root),并写入本地的缓存目录,实际调用的是这个新生成的文件,最后再删除缓存即可。

根据以上方法,我完成了一个简单的python执行器。以下为调用方法和实现方式。

调用方法

 		String pyPath = "test.py"; // python文件路径
        String pyEnvironment = "python"; // 默认为python,如果使用了anaconda创建了环境,可以找到对应的路径并替换,类似于"E:\\Anaconda3\\envs\\xxx\\python.exe"。
        PythonRun pythonRun = new PythonRun(); // 创建实例
        pythonRun.setEnvironment(pyEnvironment); // 设置环境
        pythonRun.setRoot("E:\\pythonProject\\xxx\\src"); // 设置python项目的执行目录,若不设置,在调用了其它包时,可能会出现错误。如果没有import其它文件夹下的包或库,可以忽略。
        System.out.println(pythonRun.run(pyPath, "1", "2")); // 参数为:(String path, String ...args)
对应的python文件:
import sys
if __name__ == '__main__':
    x = []
    if len(sys.argv) > 1:
        x = sys.argv[1:]
    print(x)
    print("over")
打印的结果:
['1', '2']
over


Process finished with exit code 0

实现

import java.io.*;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

public class PythonRun {
    private String environment = "python";
    private String root = null;
    private String cache = "cache/";
    private boolean autoRemoveCache = true;

    public String run(String path, String ...args) throws IOException {
        path = createNewPy(path);
        List<String> inputArgs = new LinkedList<>(Arrays.asList(environment, path));  //设定命令行
        inputArgs.addAll(Arrays.asList(args));
        StringBuilder result = new StringBuilder();
        try {
            Process proc = Runtime.getRuntime().exec(inputArgs.toArray(new String[0]));  //执行py文件
            BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line).append("\n");
            }
            in.close();
            proc.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (autoRemoveCache && path != null)
            new File(path).delete();
        return result.toString();
    }

    private String createNewPy(String path) throws IOException {
        File file = new File(path);
        if (file.isFile()){
            String result = loadTxt(file);
            if (root != null){
                result = "import sys\n" +
                        "sys.path.append(\"" + root + "\")\n" + result;
            }
            String save = cache + file.getName();
            saveTxt(save, result);
            return save;
        }
        return null;
    }

    private static File saveTxt(String filename, String string){
        File file = new File(filename);
        try {
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),"UTF-8"));
            out.write(string);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }
    private String loadTxt(File file){
        StringBuilder result = new StringBuilder();
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
            String str;
            while ((str = in.readLine()) != null) {
                result.append(str).append("\n");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return result.toString();
    }

    public String getCache() {
        return cache;
    }

    public void setCache(String cache) {
        this.cache = cache;
    }

    public String getEnvironment() {
        return environment;
    }

    public void setEnvironment(String environment) {
        this.environment = environment;
    }

    public String getRoot() {
        return root;
    }

    public void setRoot(String root) {
        this.root = root;
    }

    public boolean isAutoRemoveCache() {
        return autoRemoveCache;
    }

    public void setAutoRemoveCache(boolean autoRemoveCache) {
        this.autoRemoveCache = autoRemoveCache;
    }
}

拓展

java交互式调用python程序

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值