關於JAVA呼叫Python指令碼並傳遞引數
阿新 • • 發佈:2018-12-12
JAVA 程式呼叫python指令碼目前存在兩種形式。第一種:運用JAVA本身的自帶功能;第二種:使用jython Jar包的自帶方法來呼叫python指令碼
呼叫準備:
首先你要在本地獲取LINUX環境安裝python環境,如果是JYTHON的話需要安裝JYTHON,兩者二選一,python具體安裝轉方法詳見 WINDOWS安裝PYTHON,至於JYTHON安裝方式:JYTHON官網下載 Download Jython 2.7.0 - Installer 然後自行安裝即可。
JAVA自帶方法:
public static void main(String[] args) { try { String[] params = new String[] {"python","C:\\Users\\zhonghy\\Desktop\\zhonghy\\demo.py","10","20"}; Process proc=Runtime.getRuntime().exec(params); //執行py檔案 InputStreamReader stdin=new InputStreamReader(proc.getInputStream()); LineNumberReader input=new LineNumberReader(stdin); String line; while((line=input.readLine())!=null ){ System.out.println(line);//得到輸出 } int re = proc.waitFor(); System.out.println(re); } catch (Exception e) { e.printStackTrace(); } }
具體返回值可以和指令碼提供者協商,常用的返回值為int型別,0代表指令碼呼叫成功,1代表指令碼方法呼叫失敗,2代表指令碼呼叫失敗
Jython方式
我是基於maven構建的專案,所以要引入以下依賴:
<!-- https://mvnrepository.com/artifact/org.python/jython-standalone --> <dependency> <groupId>org.python</groupId> <artifactId>jython-standalone</artifactId> <version>2.7.1</version> </dependency>
呼叫方式整理為以下工具類:
package com.mvs.utils; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.poi.ss.formula.functions.T; import org.python.core.PyFunction; import org.python.core.PyObject; import org.python.core.PyString; import org.python.util.PythonInterpreter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; /** * @ClassName: JythonUtils * @Description:TODO(jython 工具類) * @author: zhy * @Copyright: 2018 Inc. All rights reserved. * 注意: */ public class JythonUtils { private static Logger logger = LoggerFactory.getLogger(JythonUtils.class); /** * @Title: jythonInit * @Description: TODO(初始化jython) * @param: @return * @return: PythonInterpreter * @throws */ public static PythonInterpreter jythonInit(String libPath){ //初始化site 配置 Properties props = new Properties(); props.put("python.home", libPath); //python Lib 或 jython Lib,根據系統中該檔案目錄路徑 props.put("python.console.encoding", "UTF-8"); props.put("python.security.respectJavaAccessibility", "false"); props.put("python.import.site", "false"); Properties preprops = System.getProperties(); PythonInterpreter.initialize(preprops, props, new String[0]); //建立PythonInterpreter 物件 PythonInterpreter interp = new PythonInterpreter(); return interp; } /** * @Title: loadPythonFile * @Description: TODO(載入python 原始碼檔案,) * @param: @param interp * @param: @param filePath ,比如:F:\\jpython_jar\\jpythonTest\\pythonTest.py 或/testpython/test.py * @param: @return * @return: PythonInterpreter * @throws */ public static PythonInterpreter loadPythonFile(PythonInterpreter interp, String filePath){ interp.execfile(filePath); return interp; } /** * @Title: loadPythonFunc * @Description: TODO(載入python 原始碼檔案中的某個方法) * @param: @param interp * @param: @param functionName * @param: @return * @return: PyFunction * @throws */ public static PyFunction loadPythonFunc(PythonInterpreter interp, String functionName){ //載入方法 PyFunction func = (PyFunction) interp.get(functionName,PyFunction.class); return func; } /** * @Title: execFunc * @Description: TODO(執行無參方法,返回PyObject) * @param: @param func * @return: PyObject * @throws */ public static PyObject execFunc(PyFunction func){ PyObject pyobj = func.__call__(); return pyobj; } /** * @Title: execFuncToString * @Description: TODO(執行無參方法,返回一個字串) * @param: @param func * @param: @return * @return: String * @throws */ public static String execFuncToString(PyFunction func){ PyObject pyobj = execFunc(func); return (String) pyobj.__tojava__(String.class); } /** * @Title: execFuncToString * @Description: TODO(執行有參方法,返回一個字串) * @param: @param func * @param: @param paramName ,引數名 * @param: @return * @return: String * @throws */ /*public static String execFuncToString2(PyFunction func, JSONObject object){ String result = ""; if(object.get("voiceContent")!=null) { if(object.get("voiceSender")!=null) { func.__call__(new PyString("1"),new PyString("2"),new PyString("3")); } } return null; }*/ /** * @Title: execFuncToInteger * @Description: TODO(執行無參方法,返回一個Integer) * @param: @param func * @param: @return * @return: Integer * @throws */ public Integer execFuncToInteger(PyFunction func){ PyObject pyobj = execFunc(func); return (Integer) pyobj.__tojava__(Integer.class); } /** * @Title: execFuncToList * @Description: TODO(執行無參方法,返回一個List) * @param: @param func * @param: @return * @return: List<T> * @throws */ @SuppressWarnings("unchecked") public List<T> execFuncToList(PyFunction func){ PyObject pyobj = execFunc(func); return (List<T>) pyobj.__tojava__(List.class); } /** * @Title: execFuncToMap * @Description: TODO(執行無參方法,返回一個Map<String, Object>) * @param: @param func * @param: @return * @return: Map<String,Object> * @throws */ @SuppressWarnings("unchecked") public Map<String, Object> execFuncToMap(PyFunction func){ PyObject pyobj = execFunc(func); return (Map<String, Object>) pyobj.__tojava__(Map.class); } public void execFuncToByParamsList(PyFunction func, List<T> paramsList){ } public static int sendVoiceByJava(JSONObject object, String alertNum) { int re = 1; try { if(object.get("pythonMethod")==null||object.get("pythonLib")==null||object.get("voiceScript")==null) { logger.error("當前配置的python指令碼引數錯誤,請先檢查引數................."); }else { List<String> paramLst = new ArrayList<String>(); paramLst.add("python");// paramLst.add((String)object.get("voiceScript")); paramLst.add(object.get("voiceRecevier")==null?null:object.getString("voiceRecevier")); if(object.get("voiceContent")!=null&&object.get("voiceKeys")!=null) { String[] params = object.getString("voiceKeys").split(",", -1); for(int i = 0;i<params.length;i++) { JSONArray parseArray = JSON.parseArray(object.getString("voiceContent")); if(parseArray.getJSONObject(i).get(params[i])==null) { paramLst.add(null); }else { paramLst.add(parseArray.getJSONObject(i).getString(params[i])); } } logger.info("Python Params Are: "+paramLst.toString()); Process process = Runtime.getRuntime().exec((String[])paramLst.toArray()); re = process.waitFor(); } } } catch (Exception e) { logger.error("Python指令碼呼叫異常............................", e); re = 2; } return re; } public static boolean sendVoiceByJython(JSONObject object, String alertNum) { boolean flag = false; try { if(object.get("pythonMethod")==null||object.get("pythonLib")==null||object.get("voiceScript")==null) { logger.error("當前配置的python指令碼引數錯誤,請先檢查引數................."); }else { PythonInterpreter interp = jythonInit(object.getString("pythonLib")); //獲取py指令碼路徑 interp = loadPythonFile(interp,object.getString("voiceScript")); //設定引數 //interp.set("voiceSender", object.get("voiceSender")==null?null:object.getString("voiceSender")); interp.set("voiceRecevier", object.get("voiceRecevier")==null?null:object.getString("voiceRecevier")); if(object.get("voiceContent")!=null&&object.get("voiceKeys")!=null) { String[] params = object.getString("voiceKeys").split(",", -1); for(int i = 0;i<params.length;i++) { JSONArray parseArray = JSON.parseArray(object.getString("voiceContent")); if(parseArray.getJSONObject(i).get(params[i])==null) { interp.set(params[i], null); }else { interp.set(params[i], parseArray.getJSONObject(i).getString(params[i])); } } PyFunction func = loadPythonFunc(interp, object.getString("pythonMethod")); PyObject pyObj = func.__call__(); flag = (boolean) pyObj.__tojava__(Boolean.class); } } } catch (Exception e) { logger.error("Python指令碼呼叫異常............................", e); } return flag; } public static void main(String[] args) { PythonInterpreter interpreter = jythonInit("D:\\Devlop\\python"); interpreter.execfile("C:\\Users\\zhonghy\\Desktop\\zhonghy\\demo.py"); PyFunction function = (PyFunction)interpreter.get("my_test",PyFunction.class); PyObject pyobject = function.__call__(new PyString("huzhiwei"),new PyString("25")); System.out.println("anwser = " + pyobject.toString()); /* try { String[] params = new String[] {"python","C:\\Users\\zhonghy\\Desktop\\zhonghy\\demo.py","10","20"}; Process proc=Runtime.getRuntime().exec(params); //執行py檔案 InputStreamReader stdin=new InputStreamReader(proc.getInputStream()); LineNumberReader input=new LineNumberReader(stdin); String line; while((line=input.readLine())!=null ){ System.out.println(line);//得到輸出 } int re = proc.waitFor(); System.out.println(re); } catch (Exception e) { e.printStackTrace(); }*/ } }
這裡要注意的是你在初始化Jython物件的時候的home引數可以是PYTHON的安裝路徑也可以是JYTHON的安裝路徑
測試PY指令碼
def my_test(name, age):
print ("name: "+name)
print ("age: "+age)
return "success"
需要注意的是,如果執行出錯說你python語法異常,那麼你就要好好檢查下語法了,python2與3各個版本的語法都是不同的。
執行結果(Jython方式)
name: huzhiwei
age: 25
anwser = success
執行結果(JAVA自帶方式)
0
需要注意的是:如果你用的是jython初始化的方式制定了一些預設引數是不會報cp0錯誤的,雖然這個錯誤不影響程式執行,但是如果你是JAVA形式執行python指令碼,那麼你需要在RUN CONFIGURATION中指定以下引數:
-Dpython.console.encoding=UTF-8
沒事可以寫一些簡單的指令碼來測試呼叫是否成功,這裡程式並沒有獲取到PYTHON輸出的資料,具體問題正在檢查中,有興趣的可以留言一起探討。