Java调用python项目实战

  项目中有用到Java调用python的需求,经过各种坑之后,根据业务需求,最终实现Java调用Python的各种情况,现在将总结如下,当然调用的也是Jython,具体原因,下面会介绍,先将代码贴出来。 

    这种方法是调用python文件的函数 ,并且需要将函数中的参数由Java数据类型转换为python的数据类型       

                 

org.python
jython
2.7.0


org.python
jython-standalone
2.7.0

public class JythonExecPyFile {

private static Log logger = LogFactory.getLog(JythonExecPyFile.class);


  public static PythonInterpreter getPythonEnterpreter(String jythonHome,String jythonJsonHome,String pythonRuleDir){


    Properties props = new Properties();
    //props.put("python.home", "path to the Lib folder");
    props.put("python.home", jythonHome);
    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 = new PythonInterpreter();


    PySystemState sys = Py.getSystemState();
    
    sys.path.add(jythonJsonHome);
    sys.path.add(pythonRuleDir);
    //logger.info("jythonHome: " + jythonHome +"    jythonJsonHome: " + jythonJsonHome + "    pythonRuleDir: " + pythonRuleDir);
    return pythonInterpreter;
  }


  public static void addPythonThirdPartLib(String thirdLibPath){
    PySystemState sys = Py.getSystemState();
    sys.path.add(thirdLibPath);
    sys.path.add(SettingConfiguration.getValue("pythonDir"));
  }




  public static void cleanup(PythonInterpreter interpreter){
    if(interpreter != null){
      interpreter.close();
    }
  }
  
  public static void main(String[] args) {


    PythonInterpreter pythonEnterpreter = getPythonEnterpreter(SettingConfiguration.getValue("jPythonHome"),SettingConfiguration.getValue("jythonJsonHome"),SettingConfiguration.getValue("pythonDir"));
    
    System.out.println("-----------------------------调用有参数python方法执行方法-----------------------------");
    String fileNameWithParams = "D:\\Java\\python344\\age.py";
    pythonEnterpreter.execfile(fileNameWithParams);
    PyFunction func = (PyFunction) pythonEnterpreter.get("judge_age",PyFunction.class);
    PyObject pyobj = func.__call__(new PyString("2000-11-11"),new PyInteger(1));
    
    System.out.println("pyObj: " + pyobj);
    
    System.out.println("-----------------------------调用无参数python方法执行方法-----------------------------");
    String fileNameNoParams = "D:\\svnProject\\testConnectDB.py";
    pythonEnterpreter.execfile(fileNameNoParams);
    PyFunction func2 = (PyFunction) pythonEnterpreter.get("say",PyFunction.class);
    PyObject pyobj2 = func2.__call__();
    System.out.println("pyObj: " + pyobj2);
    
    JythonExecPyFile.cleanup(pythonEnterpreter);

  }

而为了更好的封装,将调用python的参数放到list中,而将返回的数据放到dict中,python将dict转换为json串,然后在java接受到返回结果之后,将json串在转换成java的map类型即可。

public class RuleAndModelExecuteFunction {
  private static Log logger = LogFactory.getLog(RuleAndModelExecuteFunction.class);
  /**
   * 规则一 根据文件名、函数名称 参数列表 执行对应的规则或者模型     0 pass       1 reject      2 nodata
   * param :fileName, functionName,params,params where from the params of python ,And
   * if contact 为null,或者长度为0,或者为空字符串  则 empty_contacts=1  (反欺诈规则结果)anti_fraud_rules_result='reject'
   * else  anti_fraud_rules_result=‘pass'  empty_contacts=0    0 pass 1
   */


  public static String ruleExecuteMethod(String fileName,String functionName,Object... params){
logger.info("ruleExecuteMethod param------ fileName: " + fileName + "  functionName: " + functionName);  
    String returnResult = "";
List paramList = new ArrayList();
    for(Object obj:params){
      paramList.add(obj);
    }
    String fileNamePath = SettingConfiguration.getValue(fileName);
    Integer defaultResult = 2;
    
    PythonInterpreter pythonInterpreter = null;
    PyObject pyResult  = new PyObject();
    try {
      pythonInterpreter = JythonExecPyFile.getPythonEnterpreter(SettingConfiguration.getValue("jythonHome"),SettingConfiguration.getValue("jythonJsonHome"),SettingConfiguration.getValue("pythonDir"));
      pythonInterpreter.execfile(fileNamePath);
      PyFunction func = (PyFunction) pythonInterpreter.get(functionName,PyFunction.class);
      pyResult = func.__call__(new PyList(paramList));
    }catch (Exception e){
      defaultResult = 4;
      logger.error("ruleExecuteMethod param------ fileName: " + fileName + "  functionName: " + functionName + "\n" + e.getStackTrace());
      e.printStackTrace();
      return RiskRuleResultEnum.fromValue(defaultResult).getValue();
    }finally {
      JythonExecPyFile.cleanup(pythonInterpreter);
    }
    //pyResult返回的结果由原来的String类型修改为和模型一样,返回的Map类型
   /* if(pyResult != null){
        String pyResultStr = pyResult.toString();
        defaultResult = Integer.valueOf(pyResultStr);
        logger.info("RuleAndModelExecuteFunction ruleExecuteMethod result: " + pyResult.toString());
      }else {
        logger.info("RuleAndModelExecuteFunction ruleExecuteMethod result: " + pyResult);
      }*/
    if(pyResult != null){
    Map returnMap = JacksonUtil.convertJson2Map(pyResult.toString());
   if(returnMap.get("result") == null){
    returnResult = RiskRuleResultEnum.fromValue(defaultResult).getValue();
       logger.info("ruleExecuteMethod param------ fileName: " + fileName + "  functionName: " + functionName + " result为空,设置为默认值: " + defaultResult);
   }else {
    returnResult = RiskRuleResultEnum.fromValue((Integer) returnMap.get("result")).getValue();
    logger.info("ruleExecuteMethod param------ fileName: " + fileName + "  functionName: " + functionName + " result: " + defaultResult);
   }
    }else{
    returnResult = RiskRuleResultEnum.fromValue(defaultResult).getValue();
    }
    logger.info("ruleExecuteMethod result: " + returnResult );
    return returnResult;
  }


  public static Map ModelExecuteMethod(String fileName,String functionName,Object... params){
logger.info("ModelExecuteMethod param------ fileName: " + fileName + "  functionName: " + functionName);  
Map resultMap = new HashMap();
Integer defaultResult = 2;
Double defaultData = new Double(0.00);
    List paramList = new ArrayList();
    for(Object obj:params){
      paramList.add(obj);
    }


    String fileNamePath = SettingConfiguration.getValue(fileName);
    logger.info("fileNamePath:"+fileNamePath);
    PythonInterpreter pythonInterpreter = null;
    PyObject pyResult = null;
    try {
      pythonInterpreter = JythonExecPyFile.getPythonEnterpreter(SettingConfiguration.getValue("jythonHome"),SettingConfiguration.getValue("jythonJsonHome"),SettingConfiguration.getValue("pythonDir"));
      pythonInterpreter.execfile(fileNamePath);
      PyFunction func = (PyFunction) pythonInterpreter.get(functionName,PyFunction.class);
      PyList pyList = new PyList(paramList);
      pyResult = func.__call__(pyList);
    }catch (Exception e){
      defaultResult = 4;
      defaultData = new Double(-1);;
      logger.error("ModelExecuteMethod param------ fileName: " + fileName + "  functionName: " + functionName + "\n" + e.getStackTrace());
      resultMap.put("result", RiskRuleResultEnum.fromValue(defaultResult).getValue());
      resultMap.put("data",defaultData.toString());
      e.printStackTrace();
      return resultMap;
    }finally {
      JythonExecPyFile.cleanup(pythonInterpreter);
    }
    logger.info("return result:"+pyResult.toString());
    Map returnMap = JacksonUtil.convertJson2Map(pyResult.toString());
    if(returnMap.get("result") == null){
    resultMap.put("result",RiskRuleResultEnum.fromValue(defaultResult).getValue());
        logger.info("ModelExecuteMethod param------ fileName: " + fileName + "  functionName: " + functionName + " result为空,设置为默认值: " + defaultResult);
    }else {
    resultMap.put("result",RiskRuleResultEnum.fromValue((Integer) returnMap.get("result")).getValue());
    }
    if(returnMap.get("data") == null){
      resultMap.put("data",defaultData.toString());
      logger.info("ModelExecuteMethod param------ fileName: " + fileName + "  functionName: " + functionName + " data为空,设置为默认值: " + defaultData);
    }else {
    logger.info("ModelExecuteMethod param------ fileName: " + fileName + "  functionName: " + functionName + " data为空,设置为默认值: " + returnMap.get("data"));
      resultMap.put("data",returnMap.get("data").toString());
    }
    
    if (returnMap.get("antifraud_model_saved")!=null) {
    resultMap.put("antifraud_model_saved", JsonUtils.toJson(returnMap.get("antifraud_model_saved")));
}
    if (returnMap.get("android_new_saved")!=null) {
        resultMap.put("android_new_saved", JsonUtils.toJson(returnMap.get("android_new_saved")));
}
    if (returnMap.get("profile_model_saved")!=null) {
    resultMap.put("profile_model_saved", JsonUtils.toJson(returnMap.get("profile_model_saved")));
}
   
    logger.info("RuleAndModelExecuteFunction ModelExecuteMethod result: " +pyResult.toString() );
    return resultMap;
  }
  
  public static Map collectionExecuteMethod(String fileName,String functionName,Object... params){
logger.info("ModelExecuteMethod param------ fileName: " + fileName + "  functionName: " + functionName);  
Map resultMap = new HashMap();
    
List paramList = new ArrayList();
    for(Object obj:params){
      paramList.add(obj);
    }


    String fileNamePath = SettingConfiguration.getValue(fileName);
    logger.info("fileNamePath:"+fileNamePath);
    PythonInterpreter pythonInterpreter = null;
    PyObject pyResult = null;
    try {
      pythonInterpreter = JythonExecPyFile.getPythonEnterpreter(SettingConfiguration.getValue("jythonHome"),SettingConfiguration.getValue("jythonJsonHome"),SettingConfiguration.getValue("pythonDir"));
      pythonInterpreter.execfile(fileNamePath);
      PyFunction func = (PyFunction) pythonInterpreter.get(functionName,PyFunction.class);
      PyList pyList = new PyList(paramList);
      pyResult = func.__call__(pyList);
    }catch (Exception e){
      logger.error("ModelExecuteMethod param------ fileName: " + fileName + "  functionName: " + functionName + "\n" + e.getStackTrace());
      resultMap.put("result", "error");
      resultMap.put("data","-1");
      e.printStackTrace();
      return resultMap;
    }finally {
      JythonExecPyFile.cleanup(pythonInterpreter);
    }
    logger.info("return result:"+pyResult.toString());
    Map returnMap = JacksonUtil.convertJson2Map(pyResult.toString());
   
    resultMap.put("result", returnMap.get("result").toString());
    resultMap.put("data", returnMap.get("data").toString());
    
    logger.info("RuleAndModelExecuteFunction ModelExecuteMethod result: " +returnMap);
    return resultMap;

  }

public static Map convertJson2Map(String json) {
JsonFactory factory = new JsonFactory();
ObjectMapper mapper = new ObjectMapper(factory);
TypeReference> typeRef = new TypeReference>() {
};
try {
return mapper.readValue(json, typeRef);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;

}

通过这种封装之后,完成了最终的封装,并作为工具类进行调用。

Java调用python由三种方式,分别如下:

第一种方式:

public class HelloPython {
    public static void main(String[] args) {
        PythonInterpreter interpreter = new PythonInterpreter();
        interpreter.exec("print('hello')");
    }
}

什么是 PythonInterpreter 呢?它的中文意思即“ Python 解释器”。我们知道 Python 程序都是通过解释器执行的,上面的代码就是在 JVM 中创建一个“ Python 解释器”对象,模拟 Python 解释器的行为,通过 exec(" Python 语句") 直接在 JVM 中执行 Python 代码,代码的输出结果为:hello,需要提醒各位的是,该程序运行速度相较正常的 Java or Python 程序都要慢那么一点。

第二种方式:在项目中实际用到,执行的是python文件中的函数,见上面

第三种方式:通过解释器直接执行python文件

#open files
 
print 'hello'
number=[ 3 , 5 , 2 , 0 , 6 ]
print number
number.sort()
print number
number.append( 0 )
print number
print number.count( 0 )
print number.index( 5 )


import org.python.util.PythonInterpreter;
 
public class FirstJavaScript {
   public static void main(String args[]) {
 
     PythonInterpreter interpreter = new PythonInterpreter();
     interpreter.execfile( "C:\\Python27\\programs\\input.py" );
   } // main
}

第四种方式:该方式是否可以调用python的第三方模块,没有运行,用需求的朋友可以执行一个程序就可以验证

由于 Jython 运行过慢并且不支持第三方的 Python 模块,通过 Java 代码执行一段终端命令来调用 Python 脚本,根据具体问题决定如何交互可能才是实际中真正会用到的方式(详见下面的举例代码)。

举例代码:下面是一个可以识别很粗的手写数字写的一个小程序,界面上引用了 core java 上的一段代码:

复制代码
import java.io.*;

class PyCaller {
    private static final String DATA_SWAP = "temp.txt";
    private static final String PY_URL = System.getProperty("user.dir") + "\\test.py";

    public static void writeImagePath(String path) {
        PrintWriter pw = null;
        try {
            pw = new PrintWriter(new FileWriter(new File(DATA_SWAP)));
        } catch (IOException e) {
            e.printStackTrace();
        }

        pw.print(path);
        pw.close();
    }

    public static String readAnswer() {
        BufferedReader br;
        String answer = null;
        try {
            br = new BufferedReader(new FileReader(new File(DATA_SWAP)));
            answer = br.readLine();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return answer;
    }

    public static void execPy() {
        Process proc = null;
        try {
            proc = Runtime.getRuntime().exec("python " + PY_URL);
            proc.waitFor();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 测试码
    public static void main(String[] args) throws IOException, InterruptedException {
        writeImagePath("D:\\labs\\mytest\\test.jpg");
        execPy();
        System.out.println(readAnswer());
    }
}
复制代码

运行流程:Java Swing 界面接收用户输入 --> Java 将用户输入写到本地文件中 --> Java 调用本地 Python 脚本 --> Python 从本地文件拿到用户输入 --> Python 处理用户输入得到最终结果 --> Python 把最终结果写到本地文件 --> Java 对 Python 脚本的调用结束 --> Java 从本地文件中取出最终结果 --> Java 把最终结果返回给用户

完整代码链接:http://pan.baidu.com/s/1sl4l68H 

你可能感兴趣的:(Java,后台,架构)