Java调用R与Python

简介: Java调用R与Python

1 为什么我们要Java调用Python或R

Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点。Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等;Python和R在数据科学中有较高的地位,能够快速的实现特征工程、数据挖掘的建模。因此在生产中可能需要上线一些数据挖掘模型时,此时软件工程师(往往不懂数据科学)使用的工具Java和数据分析师的Python或R会有交集。

模型的线上化部署的方式有很多,比如我们可以把训练的模型转预测模型标记语言(PMML),这样Java就可以直接调用PMML;也可以做成REST API,Java通过API接口与模型进行交互,以上这些R与Python都有成熟的解决办法;最直接的办法莫过于代码与代码的对接(code2code),我们可以通过Java直接调用开发好的R模型或Python模型,完成训练,评价和预测的目的,下面我们会依次展示一个Java调用Python代码的例子和Java调用R的例子。

2.Java调用Python举栗

首先我们知道Python和Java是可以相互调用的,而本节仅举一个Java调用Python的栗子,Java调用Python的方式有很多,比如Jython(不过我不推荐大家使用,Jython版本更新缓慢,很多Python模块并没有包含,在调用的过程中会出现各种问题),我推荐大家使用命令行的方式调用Python代码或脚本,其核心方法为:

Runtime.getRuntime().exec(args1);

注意这种方式只能接收到python里print的数据。所以如果你需要返回值,可以把返回值打印出来由Java接收就OK了,请后退,我要上代码了:

首先我们要有一个Python脚本文件,比如:

import sys
import pandas as pd
import numpy as np
import sklearn
import xgboost
import lightgbm
import tensorflow as tf
import keras

def my_test(str1,str2,str3,str4):
    return "Python函数运行:java调Python测试:"+str1+str2+str3+str4
    

if __name__=="__main__":
    print("脚本名:", sys.argv[0])

    my_arg = []
    for i in range(0, len(sys.argv)):
        my_arg.append(sys.argv[i])
    print("Java传入的参数长度为:"+str(len(my_arg)))
    
    result = my_test(my_arg[1],my_arg[2],my_arg[3],my_arg[4])
    print(result)

其次我们构造一个J2py类用来调用上述Python脚本,并且实现Java数据与Python的交互(动态传参的过程):

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @title J2py.java
 * @author 作者:XuJing
 * @date 创建时间:2018年7月13日下午2:39:05
 * @version 1.0.0
 * @parameter 参数及其意义:
 * @return 返回值:
 */

public class J2py {

    public static void main(String[] args) {
        // 需传入的参数
        String a = "你好", b = "123", c = "徐静", d = "qingdao";
        System.out.println("Java中动态参数已经初始化,准备传参");
        // 设置命令行传入参数
        String[] args1 = new String[] { "python","java\\03_project\\J2py\\src\\my_model.py", a,b, c, d }; 
        //Java数据a,b,c,d传入Python
        Process pr;
        try {
            pr = Runtime.getRuntime().exec(args1); //最核心的函数

            BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream(), "gbk"));
            String line;
            List<String> lines = new ArrayList<String>();

            System.out.println("-----------------------------------------------");

            while ((line = in.readLine()) != null) {
                System.out.println(line);
                lines.add(line); //把Python的print值保存了下来

            }
            System.out.println("-------------------------------------------------");

            in.close();

            pr.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("Java调Python结束");

    }

}

在Eclipse下运行的结果如下:

Java中动态参数已经初始化,准备传参
-----------------------------------------------
脚本名: java\03_project\J2py\src\my_model.py
Java传入的参数长度为:5
Python函数运行:java调Python测试:你好123徐静qingdao
-------------------------------------------------
Java调Python结束

OK,成功了,虚线中间的部分就是我Python脚本实现的功能,并且我们实现了Java数据与Python代码的参数传递。注意一点我在Python脚本中导入了部分我们常用到的模块,这种方式Java并没有报错,也就意味着我们均可以通过Java调用这些模块构造的模型,简直是太棒了。

附:我的测试环境是Win7,Python3.6.4,JDK10.0.1,这里需要说明的是我们也可以调用Python的虚拟环境,只是把Python的代码稍作修改就可以实现。

3.Java调用R举栗

R与Java同样可以进行相互调用,实际中很多R包都是由Java完成的,本节重点依然放在Java调用R代码或脚本中,要注意的是Java调用R的方式也有很多,我们本节主要举一个Java通过Rserve调用R代码或脚本的例子,同时实现Python数据与R脚本的交互。翠花,上代码:

首先我们要有一段R脚本,在现实中可能是你用R开发好的模型,等待上线:

library(tidyverse)
library(ggplot2)
library(mlr)
library(xgboost)
library(tensorflow)
library(keras)

getSum <- function(x,y){
  m <- x + y
  print("成功执行了该R函数")  
  return(m)
}

其次,我们构造一个J2r的Java类,用来调用上面的R脚本,并且实现数据交互和在Java中自动开启Rserve:

import org.rosuda.REngine.REXP;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;

/**
 * @title J2r2.java
 * @author 作者:XuJing
 * @date 创建时间:2018年7月13日下午5:31:12
 * @version 1.0.0
 * @parameter 参数及其意义:
 * @return 返回值:
 */

public class J2r2 {

    public static void main(String[] args) {

        System.out.println(StartRserve.checkLocalRserve());

        System.out.println("准备开始Java调用R");
        System.out.println("-----------------------------------------------");
         RConnection rConnection = null;

         try {
         rConnection = new RConnection();
         rConnection.eval("source('C:/test.R')");

         } catch (RserveException e) {
         e.printStackTrace();
         } // 文件名不能带中文,否则报错:eval failed, request status: error code: 127
         int a = 2;
         int b = 3;
         int c = 4;
         int sum = 0;

         try {
         sum = rConnection.eval("getSum(" + a + "," + b + ")").asInteger();
         } catch (Exception e) {
         e.printStackTrace();
         }

         System.out.println("the sum = " + sum);
         rConnection.close();

        // 调用R代码
         System.out.println("调用R代码");

        RConnection rc = null;
        try {
            rc = new RConnection();
        } catch (RserveException e) {
            e.printStackTrace();
        }
        REXP x = null;
        try {
            x = rc.eval("library(xgboost);R.version.string");
        } catch (RserveException e) {
            e.printStackTrace();
        }
        try {
            System.out.println(x.asString());
        } catch (REXPMismatchException e) {
            e.printStackTrace();
        }
        rc.close();
        System.out.println("-----------------------------------------------");
        System.out.println("回到Java");

    }
}

在Eclipse下运行的结果如下:

准备开始Java调用R
-----------------------------------------------
the sum = 5
调用R代码
R version 3.4.0 (2017-04-21)
-----------------------------------------------
回到Java

OK成功。java同时可以调用第三方的R包,执行R脚本传参,并把数据返回给Java,这里要注意的是需要导入Rengine.jar和Rserve.jar两个压缩包,并且如果要实现Java中自动开启Rserve需要在Rserve包中找到Rserve.java源文件进行调用。

附:我的测试环境是Win7,R3.4.0,JDK10.0.1, 特别注意:不建议在Windows系统使用Rserve.

4.小结

通过以上两种简单方式我们就可以非常容易的通过Java调用R和Python封装的数据挖掘模型。实际上这是一种最简单直接的模型线上化部署的办法,在生产中我们要基于硬件和系统要求选择合理的模型线上化部署的办法。同时也可以直接使用Java或C等底层的语言开发自己的模型,减少不同代码间相互调用,提高模型的生产效率和运行速度。

原文发布时间为:2018-07-17
本文作者: 徐静
本文来自云栖社区合作伙伴“Python爱好者社区”,了解相关信息可以关注“Python爱好者社区

相关文章
|
3月前
|
机器学习/深度学习 JSON Java
Java调用Python的5种实用方案:从简单到进阶的全场景解析
在机器学习与大数据融合背景下,Java与Python协同开发成为企业常见需求。本文通过真实案例解析5种主流调用方案,涵盖脚本调用到微服务架构,助力开发者根据业务场景选择最优方案,提升开发效率与系统性能。
908 0
|
3月前
|
jenkins Shell 测试技术
|
8月前
|
JavaScript 前端开发 Java
通义灵码 Rules 库合集来了,覆盖Java、TypeScript、Python、Go、JavaScript 等
通义灵码新上的外挂 Project Rules 获得了开发者的一致好评:最小成本适配我的开发风格、相当把团队经验沉淀下来,是个很好功能……
1470 103
|
3月前
|
安全 jenkins Java
Java、Python、C++支持jenkins和SonarQube(一)
Jenkins 是一个开源的 持续集成(CI)和持续交付(CD) 工具,用于自动化构建、测试和部署软件项目。它基于 Java 开发,支持跨平台运行,并拥有丰富的插件生态系统,可以灵活地扩展功能
277 5
|
3月前
|
jenkins Java Shell
Java、Python、C++支持jenkins和SonarQube(全集)
Jenkins 是一个开源的持续集成(CI)和持续交付(CD)工具,用于自动化构建、测试和部署软件项目。它基于 Java 开发,支持跨平台运行,并拥有丰富的插件生态系统,可以灵活地扩展功能
385 1
|
3月前
|
jenkins Java 持续交付
Java、Python、C++支持Jenkins和SonarQube(三)
Python与Jenkins和SonarQube
131 1
|
3月前
|
jenkins Java 测试技术
|
5月前
|
人工智能 Java 测试技术
Java or Python?测试开发工程师如何选择合适的编程语言?
测试工程师如何选择编程语言?Java 还是 Python?多位资深专家分享建议:Python 入门简单、开发效率高,适合新手及自动化测试;Java 生态成熟,适合大型项目和平台开发。建议结合公司技术栈、个人基础及发展方向选择。长远来看,两者兼通更佳,同时关注 Go 等新兴语言。快速学习与实践才是关键。
|
7月前
|
数据采集 自然语言处理 Java
Playwright 多语言一体化——Python/Java/.NET 全栈采集实战
本文以反面教材形式,剖析了在使用 Playwright 爬取懂车帝车友圈问答数据时常见的配置错误(如未设置代理、Cookie 和 User-Agent),并提供了 Python、Java 和 .NET 三种语言的修复代码示例。通过错误示例 → 问题剖析 → 修复过程 → 总结教训的完整流程,帮助读者掌握如何正确配置爬虫代理及其它必要参数,避免 IP 封禁和反爬检测,实现高效数据采集与分析。
460 3
Playwright 多语言一体化——Python/Java/.NET 全栈采集实战
|
人工智能 安全 Java
Java和Python在企业中的应用情况
Java和Python在企业中的应用情况
383 7

推荐镜像

更多