java使用python_java调用python方法

最近做了一个东西,需要在java应用调用python的函数。查了网上若干资料,有很多种方法(直接用Jython,etc.),亲测两种最有效的方法在此分享一下。

1.使用Runtime.getRuntime()执行脚本文件

该方法可以运行含有python第三方库的程序

先建立python脚本文件 demo.py

import numpy as np

a = np.arange(12).reshape(3,4)

print(a)

java调用python程序并输出该结果

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

public class Demo {

public static void main(String[] args) {

// TODO Auto-generated method stub

Process proc;

try {

proc = Runtime.getRuntime().exec("python D:\\demo.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();

}

}

}

如若向python程序中函数传递参数并执行出结果,下面就举一例来说明一下。

同样建立python脚本文件demo2.py

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,以此类推。

2. 将python脚本写成进程为java提供服务

在java应用程序中调用python进程提供的服务。这种方法我认为是最好的!强推!!!python语言写得程序毕竟还是在python环境中执行最有效率。而且python应用和java应用可以运行在不同的服务器上,通过进程的远程访问调用。更赞的是python运行环境还可以是虚拟环境,运行tensorflow模型神马的完全没问题!

python脚本文件如下:

import socket

import sys

import threading

import numpy as np

from PIL import Image

def main():

# 创建服务器套接字

serversocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# 获取本地主机名称

host = socket.gethostname()

# 设置一个端口

port = 12345

# 将套接字与本地主机和端口绑定

serversocket.bind((host,port))

# 设置监听最大连接数

serversocket.listen(5)

# 获取本地服务器的连接信息

myaddr = serversocket.getsockname()

print("服务器地址:%s"%str(myaddr))

# 循环等待接受客户端信息

while True:

# 获取一个客户端连接

clientsocket,addr = serversocket.accept()

print("连接地址:%s" % str(addr))

try:

t = ServerThreading(clientsocket)#为每一个请求开启一个处理线程

t.start()

pass

except Exception as identifier:

print(identifier)

pass

pass

serversocket.close()

pass

class ServerThreading(threading.Thread):

# words = text2vec.load_lexicon()

def __init__(self,clientsocket,recvsize=1024*1024,encoding="utf-8"):

threading.Thread.__init__(self)

self._socket = clientsocket

self._recvsize = recvsize

self._encoding = encoding

pass

def run(self):

print("开启线程.....")

try:

#接受数据

msg = ''

while True:

# 读取recvsize个字节

rec = self._socket.recv(self._recvsize)

# 解码

msg += rec.decode(self._encoding)

# 文本接受是否完毕,因为python socket不能自己判断接收数据是否完毕,

# 所以需要自定义协议标志数据接受完毕

if msg.strip().endswith('over'):

msg=msg[:-4]

break

sendmsg = Image.open(msg)

# 发送数据

self._socket.send(("%s"%sendmsg).encode(self._encoding))

pass

except Exception as identifier:

self._socket.send("500".encode(self._encoding))

print(identifier)

pass

finally:

self._socket.close()

print("任务结束.....")

pass

def __del__(self):

pass

if __name__ == "__main__":

main()

在java代码中访问python进程的代码:

package hello;

import java.lang.System;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.net.InetAddress;

import java.net.Socket;

import java.io.OutputStream;

import java.io.PrintStream;

import java.io.InputStream;

public class hello {

public static void main(String[] args){

//System.out.println("Hello World!");

// TODO Auto-generated method stub

try {

InetAddress addr = InetAddress.getLocalHost();

String host=addr.getHostName();

//String ip=addr.getHostAddress().toString(); //获取本机ip

//log.info("调用远程接口:host=>"+ip+",port=>"+12345);

// 初始化套接字,设置访问服务的主机和进程端口号,HOST是访问python进程的主机名称,可以是IP地址或者域名,PORT是python进程绑定的端口号

Socket socket = new Socket(host,12345);

// 获取输出流对象

OutputStream os = socket.getOutputStream();

PrintStream out = new PrintStream(os);

// 发送内容

out.print( "F:\\xxx\\0000.jpg");

// 告诉服务进程,内容发送完毕,可以开始处理

out.print("over");

// 获取服务进程的输入流

InputStream is = socket.getInputStream();

BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8"));

String tmp = null;

StringBuilder sb = new StringBuilder();

// 读取内容

while((tmp=br.readLine())!=null)

sb.append(tmp).append('\n');

System.out.print(sb);

// 解析结果

//JSONArray res = JSON.parseArray(sb.toString());

} catch (IOException e) {

e.printStackTrace();

}finally {

try {if(socket!=null) socket.close();} catch (IOException e) {}

System.out.print("远程接口调用结束.");

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值