Python和Java python和java可以混用吗

您所在的位置:网站首页 python和java可以混用吗 Python和Java python和java可以混用吗

Python和Java python和java可以混用吗

2023-10-01 20:45| 来源: 网络整理| 查看: 265

前言

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-8

2. 可是我的代码中没有中文哪,怎么会这样报编码异常呢?抱着试试的态度,我增加了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