Java调用Python脚本 Java调用Python脚本传递数据并返回计算结果
SL_World 人气:0想了解Java调用Python脚本传递数据并返回计算结果的相关内容吗,SL_World在本文为您仔细讲解Java调用Python脚本的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:Java调用Python脚本,Java调用Python,下面大家一起来学习吧。
需求:最近在使用基于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代码后得到如下结果
加载全部内容