写在前面
在微服务大行其道的今天,对于将程序进行嵌套调用的做法其实并不可取,甚至显得有些愚蠢。当然,之所以要面对这个问题,或许是因为一些历史原因,或者仅仅是为了简单。这里有一个需求:需要在java程序中调用python程序。在这里做一个总结。
Java调用python
首先,不管是windows还是linux系统,需要有python的运行环境(安装有python3.6)
1.直接使用Runtime.getRuntime()执行脚本文件
eg1:

public class InvokeByRuntime {
public static void main(String[] args) throws IOException, InterruptedException {
        String exe = "python";
        String command = "D:\\calculator_simple.py";
        String num1 = "1";
        String num2 = "2";
        String[] cmdArr = new String[] {exe, command, num1, num2};
        Process process = Runtime.getRuntime().exec(cmdArr);
        InputStream is = process.getInputStream();
        DataInputStream dis = new DataInputStream(is);
        String str = dis.readLine();
        process.waitFor();
        System.out.println(str);
    }
}

calculator_simple.py的python代码为:

 from sys import argv
    num1 = argv[1]
    num2 = argv[2]
    sum = int(num1) + int(num2)
    print sum

eg2:

public class Demo1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Process proc;
		try {
			proc = Runtime.getRuntime().exec("python D:\\demo1.py");// 执行py文件
			//用输入输出流来截取结果
			BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
			String line = null;
			while ((line = in.readLine()) != null) {
				System.out.println(line);
			}
			in.close();
			proc.waitFor();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} 
	}
}

demo1.py

import numpy as np
 a = np.arange(12).reshape(3,4)
 print(a)

运行结果:
在这里插入图片描述
显然,在Java中通过Runtime调用Python程序与直接执行Python程序的效果是一样的,可以在Python中读取传递的参数,也可以在Java中读取到Python的执行结果。需要注意的是,不能在Python中通过return语句返回结果,只能将返回值写入到标准输出流中,然后在Java中通过标准输入流读取Python的输出值。

那么java怎么在python程序中函数传递参数并执行出结果,下面我就举例来说明一下:
eg1: 图片模糊度识别:
python代码如下:

import cv2
from sys import argv
import sys
def getImageVar(imgPath):
    image = cv2.imread(imgPath)
    img2gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    imageVar = cv2.Laplacian(img2gray, cv2.CV_64F).var()
    return imageVar
print(getImageVar(sys.argv[1]))

JAVA程序如下:
public static double blueDetect(String imgPath,String command){

    double score = 0.0;
    try {
        
        String[] args1 = new String[] { "python", command, imgPath };
        Process proc = Runtime.getRuntime().exec(args1);// 执行py文件

        BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
        String line = null;
        while ((line = in.readLine()) != null) {
            score = Double.parseDouble(line);
        }
        in.close();
        proc.waitFor();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return score;
}

运行结果为模糊度。python函数计算图片模糊度,应用的是拉普拉斯方差算法和opencv来计算的,此处定义图片清晰度低于阈值 100,标记其为“模糊”。

eg2:
python程序:

import sys

def func(a,b):
    return (a+b)

if __name__ == '__main__':
    a = []
    for i in range(1, len(sys.argv)):
        a.append((int(sys.argv[i])))

    print(func(a[0],a[1]))

其中sys.argv用于获取参数url1,url2等。而sys.argv[0]代表python程序名,所以列表从1开始读取参数。
以上代码实现一个两个数做加法的程序,下面看看在java中怎么传递函数参数,代码如下:

int a = 18;
int b = 23;
try {
	String[] args = new String[] { "python", "D:\\demo2.py", String.valueOf(a), String.valueOf(b) };
	Process proc = Runtime.getRuntime().exec(args);// 执行py文件

	BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
	String line = null;
	while ((line = in.readLine()) != null) {
		System.out.println(line);
	}
	in.close();
	proc.waitFor();
} catch (IOException e) {
	e.printStackTrace();
} catch (InterruptedException e) {
	e.printStackTrace();
}

其中args是String[] { “python”,path,url1,url2 }; ,path是python程序所在的路径,url1是参数1,url2是参数2,以此类推。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐