我的代码是用来解决java调用远程服务器python的自定义函数并在java端获取接口的返回值,适用于新手小白
如果你的pyhon代码部署在服务器上面,且可以通过命令行执行(一定要先确认自己的代码能在服务器的命令行顺利执行,且可以输出结果值),如运行这个命令python file.py,那么你可以尝试在Java端通过ssh session,然后远程执行 shell 命令 完成Java调用Python,需要注意的是,远程执行shell命令,cmd不能直接写"python file.py",必须用绝对路径,划重点!!!!,比如要写“/yourpath/bin/python /yourpath/projectname/file.py",废话不多说,直接看代码,java端需要有两个文件:shell.java和App.java,App.java是一个使用的demo,shell.java可以拿来直接用
//shell.java
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class shell {
private String host;
private String username;
private String password;
private int port = 22;
private int timeout = 60 * 60 * 1000;
public shell(String host, String username, String password, int port, int timeout) {
this.host = host;
this.username = username;
this.password = password;
this.port = port;
this.timeout = timeout;
}
public shell(String host, String username, String password) {
this.host = host;
this.username = username;
this.password = password;
}
public String execCommand(String cmd) {
JSch jSch = new JSch();
Session session = null;
ChannelExec channelExec = null;
BufferedReader inputStreamReader = null;
BufferedReader errInputStreamReader = null;
StringBuilder runLog = new StringBuilder("");
StringBuilder errLog = new StringBuilder("");
try {
// 1. 获取 ssh session
session = jSch.getSession(username, host, port);
session.setPassword(password);
session.setTimeout(timeout);
session.setConfig("StrictHostKeyChecking", "no");
session.connect(); // 获取到 ssh session
// 2. 通过 exec 方式执行 shell 命令
channelExec = (ChannelExec) session.openChannel("exec");
channelExec.setCommand(cmd);
channelExec.connect(); // 执行命令
// 3. 获取标准输入流
inputStreamReader = new BufferedReader(new InputStreamReader(channelExec.getInputStream()));
// 4. 获取标准错误输入流
errInputStreamReader = new BufferedReader(new InputStreamReader(channelExec.getErrStream()));
// 5. 记录命令执行 log
String line = null;
while ((line = inputStreamReader.readLine()) != null) {
runLog.append(line).append("\n");
}
// 6. 记录命令执行错误 log
String errLine = null;
while ((errLine = errInputStreamReader.readLine()) != null) {
errLog.append(errLine).append("\n");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (errInputStreamReader != null) {
errInputStreamReader.close();
}
if (channelExec != null) {
channelExec.disconnect();
}
if (session != null) {
session.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return runLog.toString();//返回值就是你的pyhon代码的输出值,具体可以参考我的python实现方式
}
}
如果你不确定是否成功连接到了服务器,那你可以运行’ls‘命令,如果正确返回远程服务器的目录,则说明成功连接到了服务器且可以接收服务器的print值
// App.java
public class App {
public static void main( String[] args ) {
//String cmd = "ls";
// 要执行的Python代码命令
String functionArguments = "qixingpiaochong.jpg"; // 传递给函数的参数
String cmd = "/home/Documents/anaconda3/envs/insectid/bin/python /home/Documents/homework/myproject/test.py " + functionArguments;
shell shell = new shell("ip", "username", "password");
String execLog = shell.execCommand(cmd);
System.out.println(execLog);
}
}
python代码中我自己定义的调用模型的接口,如果有人和我一样需要调用模型的接口,需要注意将所有的路径都换成绝对路径,如果你不需要访问目录或者文件,只是简单调用一下服务器的函数,那么可以不看我的自己定义的函数代码,主要看main就行,
import os
import time
import cv2
import khandy
import numpy as np
import importlib
import sys
importlib.reload(sys)
from insectid import InsectDetector
from insectid import InsectIdentifier
def detect(filename):
#current_directory = os.getcwd()
#print("Current Directory:", current_directory)
directory = "/home/Documents/homework/quarrying-insect-id-master/images"
# 使用os.path.join()将目录和文件名组合成完整的文件路径
full_path = os.path.join(directory, filename)
global detect_result
detector = InsectDetector()
identifier = InsectIdentifier()
start_time = time.time()
image = khandy.imread(full_path)
if image is None:
return None
if max(image.shape[:2]) > 1280:
image = khandy.resize_image_long(image, 1280)
image_for_draw = image.copy()
image_height, image_width = image.shape[:2]
boxes, confs, classes = detector.detect(image)
for box, conf, class_ind in zip(boxes, confs, classes):
box = box.astype(np.int32)
box_width = box[2] - box[0] + 1
box_height = box[3] - box[1] + 1
if box_width < 30 or box_height < 30:
continue
cropped = khandy.crop(image, box[0], box[1], box[2], box[3])
results = identifier.identify(cropped)
prob = results[0]['probability']
detect_result = results[0]['chinese_name'] + " : "+str(prob)
if prob < 0.10:
text = 'Unknown'
detect_result ='UnKnown'
else:
text = '{}: {:.3f}'.format(results[0]['chinese_name'], results[0]['probability'])
position = [box[0] + 2, box[1] - 20]
position[0] = min(max(position[0], 0), image_width)
position[1] = min(max(position[1], 0), image_height)
cv2.rectangle(image_for_draw, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 2)
image_for_draw = khandy.draw_text(image_for_draw, text, position, font='simsun.ttc', font_size=15)
save_file = filename[:-4]
save_directory = "/home/fypeng/Documents/homework/quarrying-insect-id-master/results"
# 使用os.path.join()将目录和文件名组合成完整的保存路径
save_path = os.path.join(save_directory, save_file + ".png")
cv2.imwrite(save_path, image_for_draw * 255)
#print(detect_result)
sys.stdout.flush() # 刷新输出缓冲区
return detect_result
# 在脚本中定义入口点
if __name__ == "__main__":
import sys
# 从命令行参数中获取参数值
name = sys.argv[1]
# 调用自己定义的函数,此处一定要有print
print(detect(name))
sys.stdout.flush() # 刷新输出缓冲区