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()); } }