Python和Java python和java可以混用吗 |
您所在的位置:网站首页 › python和java可以混用吗 › Python和Java python和java可以混用吗 |
前言 Python和Java都是当前非常热门的编程语言,它们各自有自己的优缺点。在有些场景下,我们可能需要使它们互相调用,以满足业务或者快速部署/整合的需求。关于Python和Java的相互调用,网上也有很多的博客,但都是零零散散,这里我在实践的同时,也顺便把踩到的坑都记录一下,最后会提供一个完整的Demo的地址。 这个Demo的调用过程是这样的:Java代码先调用Python,在Python中,又调用了Java代码,这就相当于整个Java代码执行过程中,有一部分是由Python执行的。 这个Demo主要使用的是Jython这个库。关于什么是Jython,有什么优缺点,可以参考这篇文章。 前置条件: 已安装JDK 已安装Python 已安装Eclipse Eclipse安装并配置PyDev 之前学习Python,一直使用的是PyCharm IDE,虽然该IDE也很好用,但在学习Java和Python互相调用的时候,还得回到Eclipse中来,因此了解到Eclipse也有Python相关的插件,叫PyDev。 Eclipse中安装PyDev的具体过程可以参考这篇文章,安装后,python文件会被自动关联。和Eclipse提供的Java Editor一样,用PyDev提供的Python editor编辑python文件时,也会有各种提示,这极大的加快了开发速度,非常好用。值得一提的是,在安装好PyDev之后,还需要为其配置Python的解释器:Window -> Preferences -> PyDev -> Interpreters -> Python Interpreter,PyDev会自动寻找已安装的Python路径,通常点击Quick Auto Config即可(如果不能自动找到已安装的Python,需要点击New来手动指定Python.exe的路径): 现在发车 我是用maven来管理依赖,先看下整个Demo项目的结构: 按照上面的描述,这里主测试类是CallPython.java,它会调用calljava.py,而calljava.py又会调用HelloWorld.java中的sayHello()方法,整个过程都有相应的输出。 其中,pom.xml中自然会引入Jython的包: org.python jython 2.5.3 接下来是CallPython.java,主要逻辑是创建了一个Jython库中的PythonInterpreter实例,然后调用指定的脚本,并传入了一个参数,但要注意: 这里通过PythonInterpreter类向Python环境中设置了一个参数name,其值为World 这里指定的python文件路径,是基于项目根目录的,这里的路径为src/calljava.py package com.my.py; import java.util.Properties; import org.python.core.PySystemState; import org.python.util.PythonInterpreter; public class CallPython { public static void main(String[] args) { //Set local variables for Python Properties properties = new Properties(); properties.put("name", "World"); System.out.println("1.In Java--------Start calling Python script file"); //Call Python script executePythonScript("src/calljava.py", properties); System.out.println("6.In Java--------End Pythion call"); } public static void executePythonScript(String scriptFile, Properties properties) { PythonInterpreter interpreter = getPythonInterpreter(properties); try { interpreter.execfile(scriptFile); } catch (Exception e) { System.out.println("Execute Python encounter exception:" + e); } } private static PythonInterpreter getPythonInterpreter(Properties properties) { PySystemState.initialize(System.getProperties(), properties, new String[0]); PythonInterpreter interpreter = new PythonInterpreter(); for (Object key : properties.keySet()) { interpreter.set((String)key, properties.get(key)); } return interpreter; } }以下是calljava.py,里面通过from java.packages来导入了要调用的类,然后直接创建该类的实例,并使用实例调用方法。注意,这里可以直接使用在Java环境中设置来的参数name: from com.my.py import HelloWorld #The [name] variable is set in Java through PythonInterpreter print("2.In Python------Parameter [name] is set to [%s]" % name) hello = HelloWorld() print("3.In Python------Now calling Java") hello.sayHello(name) print("5.In Python------Exit Python environment")最后,是这个被python调用的Java类: package com.my.py; public class HelloWorld { public void sayHello(String name) { System.out.println("4.In Java--------HelloWorld.sayHello() -->> Hello " + name); } }很简单,只是在sayHello()方法中打印了一下参数而已。到这里,这个Demo的代码就算是完成了。 结果分析 最后执行主测试类CallPython.java来看下执行结果: 从结果中可以看到,输出结果和预期一致: 第1行由CallPython.java输出 第2行由calljava.py输出,这说明Java已经调用到Python代码了,并且参数name已经传入 第3行由calljava.py输出,将用传入的name参数调用HelloWorld类的sayHello()方法 第4行由HelloWorld.java输出的,说明sayHello()方法已被成功调用,输出了name参数 第5行由calljava.py输出,说明调用Java代码已结束,回到了Python环境中 第6行由CallPython.java输出,说明调用Python结束,回到了Java环境中 整个过程看似很顺利,实际则是在踩过各种坑之后的。接下来说说本次实践踩过的坑。 踩过的坑 以下内容只是说明我在实践中遇到了哪些问题,可能不是正确的方法,仅作参考。 1. 其实最开始我是参照这篇文章写的,但是在依赖的Jython包的时候,我在mvnrepository中看到最新的版本为2.7.0,于是毫不犹豫的使用了最新稳定版本,结果执行的时候遇到了以下错误: 说“不支持的编码异常”,通过这篇文章得知,解决办法是需要在Run Configuration的VM参数中加入以下内容: -Dpython.console.encoding=UTF-82. 可是我的代码中没有中文哪,怎么会这样报编码异常呢?抱着试试的态度,我增加了VM参数,再执行,结果是: 仔细一看第一句,是说不能导入site模块,然而我压根儿不知道为什么会引入这个site模块。而且最后一句还给出了提示:通过指定python.import.site=false来避免。后来在这篇文章中看到解决办法,通过以下代码来初始化PythonInterpreter(主要是加入了这个python.import.site的配置): Properties props = new Properties(); props.put("python.import.site", "false"); Properties preprops = System.getProperties(); PythonInterpreter.initialize(preprops, props, new String[0]); PythonInterpreter interpreter = new PythonInterpreter();3. 之后,果然不报site模块的错了,但是又遇到以下问题: 搜索一番之后,在这篇文章中看到解决办法:把依赖的版本退回到2.5.2即可解决。但是我在mvnrepository中没看到2.5.2版本,只看到有2.5.3,于是才有了本文一开始的pom.xml中,直接引入了Jython的2.5.3版本。 4.降低依赖的Jython版本后,再执行,遇到以下问题: 1.In Java--------Start calling Python script file Execute Python encounter exception:IOError: (2, 'File not found - F:\\EclipseWorkspace\\JavaPythonDemo\\calljava.py') 6.In Java--------End Pythion call好吧,一看就知道,没找到要执行的Python文件,修改CallPython.java调用时的参数为src/calljava.py,再次执行,成功! 6.最后,检查第1步增加的VM参数,以及第2步增加的python.import.site参数,发现它们都是多余的,于是删除,所以得到了上述代码。 总结 在学习新知识的时候,肯定会遇到很多问题。幸运的是,这些同样的问题在我之前肯定都有人遇到过,并且也会有相应的解决办法,站在巨人的肩膀上,肯定会快很多。本次实践,虽然花了很多时间去解决问题,但是当看到执行结果是成功的时候,那种心情还是很激动的。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |