Java调用远程服务器的Python函数

Java调用远程服务器的Python函数

  • Java代码
  • Python代码
  • 结果

我一开始搜了很多资料和教程,结果全都不能用,后来我通过Shell顺利完成,我觉着这个方法可以解决很多调用服务器代码的问题包括服务器的环境是通过conda管理的,废话不多说了,直接上思路

我的代码是用来解决java调用远程服务器python的自定义函数并在java端获取接口的返回值,适用于新手小白

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代码

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()  # 刷新输出缓冲区

结果

这是我自己的在IDEA端的运行结果
Java调用远程服务器的Python函数_第1张图片
这是通过命令行在服务器端的运行结果

在这里插入图片描述
两个结果一致,大功告成

你可能感兴趣的:(java,服务器,python,人工智能,linux)