需求:最近在使用基于java编写的cloudsim 4.0云仿真平台进行虚拟机动态迁移实验,由于中间有需要用到深度强化学习算法,因此需要将集群的状态表示为二维数组,比如物理机的计算能力mips,ram,带宽等等。希望将这样的二维数组传入到带torch等第三方库的python脚本进行深度强化学习训练,所以就有二维int数组的传入,和从python计算后的结果返回读取这个需求

一、实现思路:将java中的data结构化为字符串,以命令行参数的形式传入python中

目前有几种java调用python的方法,不过能良好兼容python第三方库的方法通常是使用

process proc = runtime.getruntime().exec(args1); // 执行python脚本并传参数

如果只是简单传入几个数字,或者几个url,比如可直接写为

int num1 = 5;
int num2 = 10;
process proc = runtime.getruntime().exec(args1, string.valueof(num1), string.valueof(num2));

而如果要传入多维数组且每次传递时数组的大小会变,比如

int[][] stateint = new int[][]{{2500, 5, 2610, 2620, 2630, 2640, 2650, 2660},  // mips
                               {870,  5, 4091, 4092, 4093, 4094, 4095, 4096}}; // ram

则需要把要传入的多维数据,结构化为可分割的字符串,上述二维数组就可转变为如下字符串

“2500 5 2610 2620 2630 2640 2650 2660;870 5 4091 4092 4093 4094 4095 4096”

这样传入到python中就可以根据;和<空格>通过split()将二维数组恢复出来

二、python实现代码

import sys
from selenium import webdriver
import torch


def policy(state):
    action = [2, 1, 0, 0]
    action[0] += state[0][1]
    return action

def str2int(statestr):
    '''将完整字符串转换为二维数组'''
    statelist = []
    multivimstate = statestr.split(';')
    for singlevimstate in multivimstate:
        elements = singlevimstate.split(' ')
        singlevimlist = []
        for e in elements:
            singlevimlist.append(int(e))
        statelist.append(singlevimlist)
    return statelist

def int2str(actionintarr):
    '''将形如[0,1,0,0,0]的int动作向量转化为01000字符串,方便java处理'''
    actionstr = '';
    for e in actionintarr:
        actionstr += str(e)
    return actionstr

if __name__ == '__main__':
    state = []
    statestr = sys.argv[1];
    stateintarr = str2int(statestr)
    actionintarr = policy(stateintarr)
    actionstr = int2str(actionintarr)
    # [2+5=7, 1, 0, 0] => 7100
    print(actionstr)

三、java实现代码

import java.io.bufferedreader;
import java.io.inputstreamreader;

public class testpython {
    /**
     * 将整型state数组转换为带分隔符的字符串,方便以命令方式传递给python文件以进行计算
     * @param stateint 当前虚机 + 所有主机状态向量
     * @return
     */
    public static string state2str(int[][] stateint){
        string statestr = "";
        for (int i = 0; i < stateint.length; i++) {
            for (int j = 0; j < stateint[0].length; j++) {
                if (j == 0)  statestr += string.valueof(stateint[i][j]);
                else         statestr += " " + string.valueof(stateint[i][j]);
            }
            if (i != stateint.length - 1)  statestr += ";";
        }
        return statestr;
    }

    public static void main(string[] args) throws exception {
        // python文件地址(linux)
        string pypath = "/xxxx/xxxx.py";

        int[][] stateint = new int[][]{{2500, 5, 2610, 2620, 2630, 2640, 2650, 2660},  // mips
                                       {870,  5, 4091, 4092, 4093, 4094, 4095, 4096}}; // ram
        // 将整型state数组转换为带分隔符的字符串,方便以命令方式传递给python文件以进行计算
        string statestr = state2str(stateint);
        string[] args1 = new string[] {"python", pypath, statestr};
        // 执行python文件,并传入参数
        process proc = runtime.getruntime().exec(args1);
        // 获取python输出字符串作为输入流被java读取
        bufferedreader in = new bufferedreader(new inputstreamreader( proc.getinputstream() ));
        string actionstr = in.readline();
        if (actionstr != null)
            system.out.println(actionstr);
            
        in.close();
        proc.waitfor();

        // 将获取的字符串分割为字符串数组,然后逐个元素转换为int并求和
        string nums[] = actionstr.split("");
        int sum = 0;
        for (int i = 0; i < nums.length; i++)
            sum += integer.valueof(nums[i]);
        system.out.println("求和为:" + sum);
    }
}

运行java代码后得到如下结果

到此这篇关于java调用python脚本传递数据并返回计算结果的文章就介绍到这了,更多相关java调用python脚本内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!