如何在Java中执行Python模块?从认识JEP库开始

让我们从认识JEP库开始。

关注《Java学研大本营》

本教程基于带M1芯片的macOSX,用于Python 3.8/3.9和Java 11。

介绍

从我的实践来讲,我遇到的上一个挑战是,当基础应用引擎是Java的时候,我按常理应该添加一个新的机器学习功能。但是,这里的关键却是,ML功能是在Python里面。

那么我们要怎么做呢?我们应用什么样的解决方案来完成这个任务?

其中一个工作方案是在docker中运行这个服务。或者我们可以找到另一个更有效的有利于生产的解决方案:通过Jep库(Java Embedded Python)直接从Java代码中执行python代码。

什么是JEP库?

下面是GitHub上的FAQ中的一些引文。

Jep使用JNI和CPython API来启动JVM中的Python解释器。当你在Java中创建一个Interpreter实例时,将为该Java Interpreter实例创建一个Python解释器,并保留在内存中,直到用Interpreter.close()关闭该Interpreter实例。

由于需要管理一致的Python线程状态,创建Interpreter实例的线程必须在对该Interpreter实例的所有方法调用中重复使用。

这里有一个关于Python模块执行的评论。

Jep应该与任何纯Python模块一起工作。它可以与各种CPython扩展一起工作。开发人员报告说,Jep可以与NumPy、Scipy、Pandas、TensorFlow、Matplotlib、cvxpy等一起工作。

速度性能是一个至关重要的指标,特别是当你的应用程序处理大数据时。我在研究中的测试表明,使用JEP几乎是纯粹的python执行。

如何为你的项目设置JEP?

假设你的系统里有Java(Maven)和Python。在Java项目中,在pom.xml文件中,你设置了一个依赖项。

在项目终端运行。

mvn clean install
or
mvn clean install -DskipTests

你在Java中安装了JEP!

要在Python中安装JEP,运行:

pip install jep 

该命令安装最新的JEP版本。如果你需要,你可以指定一个特定的JEP版本。在我的例子中,我使用JEP 4.0.3版本。

这里的版本不兼容是实质性的。你将采取的Python版本和Jep库版本越低,你将使用越复杂的java语法(反之亦然)。但是最新的JEP版本可以轻易地执行JEP旧版本的语法。

在你的系统中,必须要设置一个环境变量。对于macOSX,就像在终端运行一样。

export DYLD_LIBRARY_PATH="<your_user>/myenv/lib/python3.8/site-packages/jep"$DYLD_LIBRARY_PATH

不要忘了在你的~/.zshrc文件中加入同样的一行! JEP在macOS上寻找libjep.jnilib文件,在Linux上寻找libjep.so文件。

除此之外,对于Linux系统,它将是一个不同的环境变量名称。

export LD_LIBRARY_PATH="<your_user_path>/myenv/lib/python3.8/site-packages/jep"$LD_LIBRARY_PATH

你设置了JEP库。现在你可以直接从Java中执行Python。

Python 3.8 macOSX M1芯片的语法

首先,我们应该定义JEP库的路径 (特别是Java将在哪里搜索Python来执行),并初始化MainInterpreter对象。

import jep.*;
import jep.MainInterpreter;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;


String pythonFolder = System.getenv("DYLD_LIBRARY_PATH");

//define the JEP library path
String jepPath = pythonFolder + "/jep/libjep.jnilib";

if (!Files.exists(Path.of(jepPath))){            
   jepPath = pythonFolder + "/jep/libjep.so";        
}
//initialize the MainInterpreter   
MainInterpreter.setJepLibraryPath(jepPath);

然后,设置JEP的配置(我们应该把Python库添加到操作和我们的项目文件夹中)。然后,创建一个SharedInterpreter对象。一个SharedInterpreter将直接执行Python代码或Python执行文件。

jep.JepConfig jepConf = new JepConfig();   

jepConf.addIncludePaths("/Users/galinablokh/Documents/POCNerClassificationSDK/src/main/java");    

jepConf.addIncludePaths(pythonFolder);

SharedInterpreter.setConfig(jepConf);

SharedInterpreter subInterp = new SharedInterpreter();
view raw setUpJepConfig.java hosted with ❤ by GitHub

我有一个Python文档,有两个简单的函数来检查JEP的工作。一个函数应该使用本地Python库来搜索目录中的特定文件。第二个函数调用更复杂的Python库,Spacy。确保你在Jep运行之前在Python中安装了Spacy库和下载的模型。

import glob
import os

import spacy

def get_c_path(pathlib, extension):
    path_list = glob.glob(f'{pathlib}/' + f'{extension}')
    return path_list


def run_spacy_nlp(sentence):
    nlp = spacy.load("en_core_web_sm")
    doc = nlp(sentence)
    return [(token.text, token.lemma_, token.pos_, token.tag_,
             token.dep_, token.shape_, token.is_alpha, token.is_stop) for token in doc]

现在,让我们从 Java 中运行 Python 文档函数。

// run function from the python_functions.py document
subInterp.eval("import python_functions as p");

subInterp.eval("res_spacy = p.run_spacy_nlp('Apple is looking at buying U.K. startup for $1 billion')");

ArrayList result = (ArrayList) subInterp.getValue("res_spacy");

   for (Object item:result) {
       System.out.println(item.toString());
        }

输出的结果是。

>>> [Apple, Apple, PROPN, NNP, nsubj, Xxxxx, true, false]
>>> [is, be, AUX, VBZ, aux, xx, true, true]
>>> [looking, look, VERB, VBG, ROOT, xxxx, true, false]
>>> [at, at, ADP, IN, prep, xx, true, true]
>>> [buying, buy, VERB, VBG, pcomp, xxxx, true, false]
>>> [U.K., U.K., PROPN, NNP, dobj, X.X., false, false]
>>> [startup, startup, VERB, VBD, dep, xxxx, true, false]
>>> [for, for, ADP, IN, prep, xxx, true, true]
>>> [$, $, SYM, $, quantmod, $, false, false]
>>> [1, 1, NUM, CD, compound, d, false, false]
>>> [billion, billion, NUM, CD, pobj, xxxx, true, false]

这真是太棒了! 我们可以直接从 Java 中调用和执行 Python! 但是等等,我在文章开头提到的其他Python版本的语法怎么办?

Python 3.9 macOSX M1芯片的语法

我之前说过,Python和Jep版本越高,Java的语法就越简单。之所以如此,是因为在Python 3.9以上版本的最新Jep版本中,JEP开发者在执行 "pip install jep "时增加了对Python路径的自动搜索。让我们看看下面的语法!

// set path for jep executing python3.9
MainInterpreter.setJepLibraryPath(jepPath);
        
// set path for python docs with python script to run
jep.JepConfig jepConf = new JepConfig();
jepConf.addIncludePaths(System.getProperty("user.dir")+"/src/main/java/");
        
//create the interpreter for python executing
Interpreter subInterp = jepConf.createSubInterpreter();

四行代码,我们就有了一个Java中的Python3.9解释器! 现在你将看到如何运行你已经看过的文档中的Python函数。

//import  .py doc with to run
subInterp.eval("import python_functions as p");

// run each function from the .py doc I
subInterp.eval("res_spacy = p.run_spacy_nlp('Apple is looking at buying U.K. startup for $1 billion')");
System.out.println(subInterp.getValue("res_spacy"));
        
//II
subInterp.eval("res_c = p.get_c_path('.idea','*.xml')");
System.out.println(subInterp.getValue("res_c"));

打印结果将与Python 3.8版本的相同。

结论

在本教程中,你得到了关于如何从任何Java应用程序中执行Python 3.8和Python 3.9版本的Python代码的清晰说明。

文章中的所有代码例子你都可以在macOSX M1芯片和Linux上运行。你只需要为每个系统正确设置Jep库即可。

参考:

  1. Jep library GitHub(https://github.com/ninia/jep)

  2. My GitHub project with code examples(https://github.com/Galina-Blokh/jep-java-python)

  3. https://medium.com/geekculture/how-to-execute-python-modules-from-java-2384041a3d6d

推荐书单

《Java编程讲义》

购买链接:https://item.jd.com/13495830.html

《Java编程讲义》根据目前Java开发领域的实际需求,从初学者角度出发,详细讲解了Java技术的基础知识。

全书共15章,包括Java开发入门,Java语言基础,Java控制结构,数组,面向对象编程,继承和多态,抽象类、接口和内部类,异常处理,Java常用类库,集合与泛型,Lambda表达式,输入-输出流,多线程,JDBC数据库技术,网络编程等内容。内容全面覆盖.Java开发必备的基础知识点,结合生活化案例展开讲解,程序代码给出了详细的注释,能够使初学者轻松领会Java技术精髓,快速掌握Java开发技能。

《Java编程讲义》适合作为高等院校相关专业的教材及教学参考书,也适合作为Java开发入门者的自学用书,还可供开发人员查阅、参考。

精彩回顾

深入理解Docker网络通信原理

详细&全面的RxJava架构原理与设计讲解

Java面试宝典大集锦

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值