java調用python程序

豐富的第三方庫使得python非常適合用于進行數據分析诗宣,最近在項目中就涉及到java調用python實現的算法。目前,java調用python主要包括三種方法:1、利用runtime在本地運行python腳本挣柬;2、通過jython調用睛挚;3、java通過rpc(遠程過程調用)調用python急黎。其中扎狱,runtime調用python實際上是通過cmd命令本地運行python腳本,對傳遞參數的長度有限制勃教;而通過jython調用的方式無法導入numpy等第三方庫淤击。通過rpc遠程調用的方式則不存在上述限制,是比較理想的方式故源。

1污抬、通過runtime調用python

代碼如下:

package pythonTest;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class pythonTest {
    public static void main(String[] args) {
        String filePath = ".\\src\\AverageEcho6211701.txt";
        String coePath = ".\\src\\OVlidar20190116.txt";
        String[] data = TxtUtil.getContentByLine(filePath,3000);
        String[] coeData = TxtUtil.getContentByLine(coePath, 500);
        System.out.println(data[0]);
        int bearing = 90;
        double decCoe = 0.25;
        try {
            String[] pythonArgs = new String[] { "python", ".\\src\\11.py", String.valueOf(bearing), String.valueOf(decCoe),
                    String.join(",", data)};
            String[] appendPythonArgs = new String[pythonArgs.length + coeData.length];
            System.arraycopy(pythonArgs, 0, appendPythonArgs, 0, pythonArgs.length);
            System.arraycopy(coeData, 0, appendPythonArgs, pythonArgs.length, coeData.length);
            Process proc = Runtime.getRuntime().exec(pythonArgs);// 執(zhí)行py文件
            // 定義Python腳本的返回值
            String result = null;
            BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String line = null;
            while ((line = in.readLine()) != null) {
                result = line;
            }
            in.close();
            proc.waitFor();
            System.out.println(result);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

通過runtime調用實際上是通過cmd命令在本地運行python腳本,參數以字符串形式進行傳遞,當字符串超出一定長度時程序會報錯印机。

java.io.IOException: Cannot run program "python": CreateProcess error=206, 文件名或擴展名太長矢腻。
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
    at java.lang.Runtime.exec(Runtime.java:620)
    at java.lang.Runtime.exec(Runtime.java:485)
    at pythonTest.pythonTest.main(pythonTest.java:22)
Caused by: java.io.IOException: CreateProcess error=206, 文件名或擴展名太長。
    at java.lang.ProcessImpl.create(Native Method)
    at java.lang.ProcessImpl.<init>(ProcessImpl.java:386)
    at java.lang.ProcessImpl.start(ProcessImpl.java:137)
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
    ... 3 more

2射赛、jython

jython是在jvm上實現的python多柑,由java編寫,jython將python源碼變異成jvm字節(jié)碼楣责,由jvm執(zhí)行對應的字節(jié)碼竣灌。使用前需要在pom文件中導入相關的jar包:

<!-- https://mvnrepository.com/artifact/org.python/jython-standalone -->
        <dependency>
            <groupId>org.python</groupId>
            <artifactId>jython-standalone</artifactId>
            <version>2.7.1</version>
        </dependency>

相關代碼如下:

package pythonTest;

import org.python.core.*;
import org.python.util.PythonInterpreter;


public class pythonTest {
    public static void main(String[] args) {
        String filePath = ".\\src\\main\\resources\\AverageEcho6211701.txt";
        String coePath = ".\\src\\main\\resources\\OVlidar20190116.txt";
        String[] data = TxtUtil.getContentByLine(filePath,3000);
        String[] coeData = TxtUtil.getContentByLine(coePath, 500);
        System.out.println(data[0]);
        int bearing = 90;
        double decCoe = 0.25;

        PythonInterpreter interpreter = new PythonInterpreter();

        interpreter.exec("import sys");
        interpreter.execfile(".\\src\\main\\python\\11.py");
        // 第一個參數為期望獲得的函數(變量)的名字,第二個參數為期望返回的對象類型
        PyFunction pyFunction = interpreter.get("add", PyFunction.class);
        int a = 5, b = 10;
        //調用函數秆麸,如果函數需要參數初嘹,在Java中必須先將參數轉化為對應的“Python類型”
        PyObject pyobj = pyFunction.__call__(new PyInteger(a), new PyInteger(b));
        System.out.println("the anwser is: " + pyobj);


    }
}

當python腳本中需要導入第三方庫時程序報錯:

Exception in thread "main" Traceback (most recent call last):
  File ".\src\main\python\11.py", line 2, in <module>
    import numpy
ImportError: No module named numpy

3、rpc遠程調用python

rpc框架實際提供了一套機制沮趣,使得應用程序之間可以進行通信削樊,采用server/client模型,客戶端調用服務端接口兔毒。目前開源的rpc框架有Dubbo漫贞、Thrift、grpc等育叁,其中dubbo僅支持java迅脐,thrift與grpc支持多語言,使用grpc實現java調用python程序豪嗽,java實現客戶端谴蔑,python實現服務端。grpc具有以下特點:1龟梦、grpc通過protobuf定義接口隐锭,可以將數據序列化成二進制編碼,大幅減少需要傳輸的數據量计贰,從而提高性能钦睡;2、grpc支持流式場景躁倒。
首先荞怒,定義protobuf接口:


syntax = "proto3";

package com.wayealCloud.mlp;

service MlpAlgorithm
{
    rpc mlpInverting(Request) returns (Result){}
}

message Request
{
    string data = 1;
    string coeData = 2;
    string bearing = 3;
    string decCoe = 4;
}

message Result
{
    string exData = 1;
}

在proto文件所在目錄下進行編譯:

python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./mlp.proto

然后,編寫python服務端程序秧秉,代碼如下:

# -*- coding: utf-8 -*-
"""
@author: yhl
@time: 2019/09/16
激光雷達反演算法
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from ETLandTraining.spark_code.micro_pulse_lidar.micro_pulse_lidar import SectionalSlopeAlgorithm, \
    FernaldAlgorithm, WaveletDenoising, move_avg, fanyan_algorithm

from concurrent import futures
from src.ETLandTraining.spark_code.micro_pulse_lidar.src import mlp_pb2_grpc, mlp_pb2

import numpy as np
import math
import matplotlib.pyplot as plt
import time
import grpc

_ONE_DAY_IN_SECONDS = 60 * 60 * 24

_HOST = '192.168.200.234'
IP = "9000"


class ServiceMain(mlp_pb2_grpc.MlpAlgorithmServicer):
    def mlpInverting(self, request, context):
        data = request.data.split(',')
        data = [item.split('  ') for item in data]
        data = np.array(data).astype('float32')
        ovlidar = request.coeData.split(',')
        ovlidar = np.array(ovlidar).astype('float32')
        bearing = int(request.bearing)
        dec_coe = float(request.decCoe)
        p1 = data[:, 1]
        p2 = data[:, 2]
        er, dec_ratio = fanyan_algorithm(bearing, p1, p2, ovlidar, dec_coe)
        return mlp_pb2.Result(exData=str(er[0]))


def serve():
    grpc_server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    mlp_pb2_grpc.add_MlpAlgorithmServicer_to_server(ServiceMain(), grpc_server)
    grpc_server.add_insecure_port("{}:{}".format(_HOST, IP))
    grpc_server.start()
    print("grpc service start")
    try:
        while True:
            time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
        grpc_server.stop(0)


if __name__ == '__main__':

    serve()

最后褐桌,編寫java客戶端程序。第一步象迎,定義protobuf接口文件且必須與python端保持一致荧嵌;第二步,在pom文件中添加相關的jar包及插件;第三部啦撮,編譯及編寫客戶端程序谭网。pom文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wayeal.cloud.mlp</groupId>
    <artifactId>mlp</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!-- https://github.com/grpc/grpc-java-->
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>1.23.0</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>1.23.0</version>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>1.23.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.2</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.9.0:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.23.0:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

客戶端程序如下:

package com.wayealCloud.mlp.mlpClient;

import com.wayealCloud.mlp.util.TxtUtil;
import io.grpc.Grpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;

import java.util.concurrent.TimeUnit;

public class MlpClient {
    private final ManagedChannel channel;
    private final MlpAlgorithmGrpc.MlpAlgorithmBlockingStub blockingStub;
    public MlpClient(String host,int port){
        channel = ManagedChannelBuilder.forAddress(host,port)
                .usePlaintext()
                .build();
        blockingStub = MlpAlgorithmGrpc.newBlockingStub(channel);
    }
    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }
    public String greet(String data,  String coeData, String bearing, String decCoe){
        Request request = Request.newBuilder()
                .setData(data)
                .setCoeData(coeData)
                .setBearing(bearing)
                .setDecCoe(decCoe)
                .build();
        Result result = blockingStub.mlpInverting(request);
        System.out.println(result.getExData());
        return result.getExData();
    }

    public static void main(String[] args) throws InterruptedException {
        String filePath = ".\\src\\main\\resources\\AverageEcho6211701.txt";
        String coePath = ".\\src\\main\\resources\\OVlidar20190116.txt";
        String[] data = TxtUtil.getContentByLine(filePath,3000);
        String[] coeData = TxtUtil.getContentByLine(coePath, 500);
        String bearing = "90";
        String decCoe = "0.25";

        MlpClient client = new MlpClient(Constants.IP, Constants.port);
        String result = client.greet(String.join(",", data), String.join(",", coeData), bearing, decCoe);
    }
}

結果如下:

0.3565467136205529

綜上所述,基于grpc逻族,java實現客戶端蜻底,python實現服務端,通過遠程調用的方式是比較理想的方法聘鳞。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末薄辅,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子抠璃,更是在濱河造成了極大的恐慌站楚,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搏嗡,死亡現場離奇詭異窿春,居然都是意外死亡,警方通過查閱死者的電腦和手機采盒,發(fā)現死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門旧乞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人磅氨,你說我怎么就攤上這事尺栖。” “怎么了烦租?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵延赌,是天一觀的道長。 經常有香客問我叉橱,道長挫以,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任窃祝,我火速辦了婚禮掐松,結果婚禮上,老公的妹妹穿的比我還像新娘锌杀。我一直安慰自己甩栈,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布糕再。 她就那樣靜靜地躺著,像睡著了一般玉转。 火紅的嫁衣襯著肌膚如雪突想。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音猾担,去河邊找鬼袭灯。 笑死,一個胖子當著我的面吹牛绑嘹,可吹牛的內容都是我干的稽荧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼工腋,長吁一口氣:“原來是場噩夢啊……” “哼姨丈!你這毒婦竟也來了?” 一聲冷哼從身側響起擅腰,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蟋恬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后趁冈,有當地人在樹林里發(fā)現了一具尸體歼争,經...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年渗勘,在試婚紗的時候發(fā)現自己被綠了沐绒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡旺坠,死狀恐怖乔遮,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情价淌,我是刑警寧澤申眼,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蝉衣,受9級特大地震影響括尸,放射性物質發(fā)生泄漏。R本人自食惡果不足惜病毡,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一濒翻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧啦膜,春花似錦有送、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至八拱,卻和暖如春阵赠,著一層夾襖步出監(jiān)牢的瞬間涯塔,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工清蚀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留匕荸,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓枷邪,卻偏偏與公主長得像榛搔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子东揣,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內容

  • 1.調用python程序不需要傳參只需獲得結果時: 直接新建java文件践惑,然后新建Process對象調用pytho...
    WM8閱讀 3,582評論 0 0
  • gRPC 是一個高性能、通用的開源RPC框架救斑,基于HTTP/2協(xié)議標準和Protobuf序列化協(xié)議開發(fā)童本,支持眾多的...
    小波同學閱讀 19,494評論 6 19
  • 原文出處:gRPC gRPC分享 概述 gRPC 一開始由 google 開發(fā),是一款語言中立脸候、平臺中立穷娱、開源的遠...
    小波同學閱讀 7,223評論 0 18
  • 1> 安裝Homebrew 2> 安裝Jenkins 此時會提示: 3> 安裝上面的提示安裝Java 安裝完成后再...
    奧個特曼閱讀 1,657評論 0 1
  • 那天我去參加小莊的婚禮。晚上运沦,一群人興致勃勃的簇擁在她們家小院里搓麻將泵额。百無聊賴的我躺在她床上玩游戲消遣,畢...
    Mmawei閱讀 297評論 0 0