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

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

                 <dependency>
<groupId>org.python</groupId>
<artifactId>jython</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.0</version>

</dependency>

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<Object> paramList = new ArrayList<Object>();
    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<String,Object> 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<String,String> ModelExecuteMethod(String fileName,String
functionName,Object... params){
logger.info("ModelExecuteMethod param------ fileName: " + fileName + "
 functionName: " + functionName);  
Map<String,String> resultMap = new HashMap<String,String>();
Integer defaultResult = 2;
Double defaultData = new Double(0.00);
    List<Object> paramList = new ArrayList<Object>();
    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<String,Object> 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<String,String> collectionExecuteMethod(String
fileName,String functionName,Object... params){
logger.info("ModelExecuteMethod param------ fileName: " + fileName + "
 functionName: " + functionName);  
Map<String,String> resultMap = new HashMap<String,String>();
    
List<Object> paramList = new ArrayList<Object>();
    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<String,Object> 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<String, Object> convertJson2Map(String json) {
JsonFactory factory = new JsonFactory();
ObjectMapper mapper = new ObjectMapper(factory);
TypeReference<HashMap<String, Object>> typeRef = new
TypeReference<HashMap<String, Object>>() {
};
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
numbernumber.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 

友情链接
ioDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信