CallPythonInJava&&Anaconda

1、场景描述

  需求:需要在Java里面调用Python写的模型。

  问题:模型在python环境里面能够直接运行,但是用Java调用时,总会发生找不到包或者找不到动态链接库等问题。

 

2、解决方法

  尝试一:

    尝试重新导入了相关的包,以及去寻找了缺失的动态链接文件。

    问题依旧存在。

  尝试二:

    尝试在命令行用anaconda虚拟环境运行和直接用虚拟环境的python解释器运行代码,

    发现,用anaconda环境能够运行,但是直接用python解释器就会出现之前的错误。

  因此,找出了运行失败的原因为:

    在python环境里面,我是使用的anaconda的虚拟环境运行代码的,

    但是在Java调用里面,我选择了使用python解释器。

    anaconda环境为我们维护了相应的包,因此能找到包,不会出错。

    但是使用python解释器时,只会到代码路径和解释器路径PYTHON_PATH下面扫描包。

    因此,有些包找不到。

  解决办法:

    在Java调用时,先激活使用的anaconda虚拟环境,再运行代码。

    修改后的代码放在文章最后。

 

3、anaconda常用命令总结

  在python项目中经常用到anaconda,在此总结一下它的一些常用命令:

anaconda换镜像源(清华源):
conda config
--add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/ conda config --set show_channel_urls yes

建立虚拟环境:
conda create -n Python3 python=3.9 pandas numpy 使用3.9的python版本 建立一个名为Python3的环境,该环境初始化时包含pandas和numpy包。

复制虚拟环境:
conda create -n 新环境名 -clone 被复制的环境名

显示所有环境:
conda info --envs 或 conda env list

激活虚拟环境:
conda activate Python3

在虚拟环境中安装包:
conda install tensorflow==2.2.0 安装tensorflow2.2.0
conda install -n 环境名 包名 指定在那个环境下安装包
pip3 install 包名           也可以使用pip安装

卸载包:
conda uninstall 包名         卸载当前环境下的包
conda uninstall -n 环境名 包名 卸载指定环境下的包
pip3 uninstall 包名 也可以使用pip管理

更新包:
conda update 包名           更新指定包
conda update --all          更新当前环境下的所有包

搜索源中存在的包
conda search 包名 模糊搜索,可使用正则表达式来匹配
conda search --full-name 包名 精准匹配

显示当前虚拟环境下的所有包:
conda list

退出虚拟环境:
conda deactivate

删除虚拟环境
conda remove -n 环境名 --all 删除指定的虚拟环境,该环境下的所有包都会被移除

 

4、代码

import java.io.*;
import java.util.concurrent.*;

/**
 * 执行python并获取执行结果
 * 实际就是Java使用【命令行】来执行python代码,
 * python执行的结果打印到输出流
 * 通过将python输出流接入到Java输入流,来获取结果
 */
public class CallPython {
    private static String condaPath;
    static {
        condaPath=System.getenv("anaconda");                                    //获取anaconda Script位置,需要先把Anaconda\ana\Scripts目录加入系统变量中,名称为anaconda
        condaPath=condaPath.replace("\\","\\\\");
    }
    private String envName="lqb";                                               //虚拟环境名称
    private String pyPath="F:\\PycharmProject\\NLP_Project\\ModelService.py ";  //python代码位置
    private String parameter="因大小交通事故等原因发生拥堵";                         //传递参数 可根据python代码自用定制

    public CallPython(){};

    public CallPython(String PYTHON_HOME, String pyPath, String parameter) {
        this.envName = PYTHON_HOME;
        this.pyPath = pyPath;
        this.parameter = parameter;
    }

    public String getPYTHON_HOME() {
        return envName;
    }

    public String getPyPath() {
        return pyPath;
    }

    public String getParameter() {
        return parameter;
    }

    public void setPYTHON_HOME(String PYTHON_HOME) {
        this.envName = PYTHON_HOME;
    }

    public void setPyPath(String pyPath) {
        this.pyPath = pyPath;
    }

    public void setParameter(String parameter) {
        this.parameter = parameter;
    }

    /**
     * 调用python代码并返回Future对象
     * @return
     */
    public Future callPython() {
        String result = null;
        try
        {
            //执行py文件
            Process proc = Runtime.getRuntime().exec(condaPath+"\\activate.bat "+envName+"&& python "+pyPath+parameter);
            //接收输出
            BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream(),"gbk"));
            //接收错误流
            BufferedReader isError = new BufferedReader(new InputStreamReader(proc.getErrorStream(),"gbk"));

            //避免IO阻塞,开启两个线程来分别读取标准输入流和错误流
            readErr(isError);

            Future F=readInFuture(in);

            proc.waitFor();
            return F;

        } catch (Exception e) {
                      e.printStackTrace();
               }
        return null;
    }

    /**
     * 获取python代码执行的错误流,并打印输出
     * @param isError 错误流
     */
    void readErr(BufferedReader isError) throws InterruptedException {
        ExecutorService ES= Executors.newCachedThreadPool();
        ES.submit(() -> {
            String lineErr=null;
            StringBuilder sb= new StringBuilder();
            try {
                while ((lineErr = isError.readLine()) != null) {
                    sb.append(lineErr);
                    sb.append("\n");
                }
                isError.close();
                System.out.println(sb);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        ES.shutdown();
    }

    /**
     * 获取python文件执行的结果(输出流),并以Future返回
     * @param in 输入流
     * @return
     */
    Future<String> readInFuture(BufferedReader in) throws InterruptedException {
        ExecutorService ES= Executors.newCachedThreadPool();
        Future F = ES.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                String line=null;
                StringBuilder sb= new StringBuilder();
                while ((line= in.readLine()) != null) {
                    sb.append(line);
                }
                in.close();
                System.out.println(sb);
                return sb.toString();
            }
        });
        ES.shutdown();
        return F;
    }

    /**
     * 获取python执行的结果,并打印
     * @param in
     */
    void readIn(BufferedReader in){
        new Thread(() -> {
            String line=null;
            StringBuilder sb= new StringBuilder();
            try{
                while ((line= in.readLine()) != null) {
                    sb.append(line);
                    sb.append("\n");
                }
                in.close();
                System.out.println(sb);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }).start();
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CallPython cp=new CallPython();
        System.out.println(cp.callPython().get());
    }
}

 

CallPythonInJava&&Anaconda

上一篇:iphone如何导出微信聊天记录到电脑?


下一篇:是男人就下100层【第一层】——高仿微信界面(3)