1. 程式人生 > >關於JAVA呼叫Python指令碼並傳遞引數

關於JAVA呼叫Python指令碼並傳遞引數

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輸出的資料,具體問題正在檢查中,有興趣的可以留言一起探討。