java执行python中文有问题_那些Java调用Python,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的路径):

132620_QNPz_1434710.png

现在发车

我是用maven来管理依赖,先看下整个Demo项目的结构:

130122_Ln3r_1434710.png

按照上面的描述,这里主测试类是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来看下执行结果:

141953_16ez_1434710.png

从结果中可以看到,输出结果和预期一致:

第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,于是毫不犹豫的使用了最新稳定版本,结果执行的时候遇到了以下错误:

142342_FEVd_1434710.png

说“不支持的编码异常”,通过这篇文章得知,解决办法是需要在Run Configuration的VM参数中加入以下内容:

-Dpython.console.encoding=UTF-8

2. 可是我的代码中没有中文哪,怎么会这样报编码异常呢?抱着试试的态度,我增加了VM参数,再执行,结果是:

143134_O4wO_1434710.png

仔细一看第一句,是说不能导入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模块的错了,但是又遇到以下问题:

144614_Hgqb_1434710.png

搜索一番之后,在这篇文章中看到解决办法:把依赖的版本退回到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参数,发现它们都是多余的,于是删除,所以得到了上述代码。

总结

在学习新知识的时候,肯定会遇到很多问题。幸运的是,这些同样的问题在我之前肯定都有人遇到过,并且也会有相应的解决办法,站在巨人的肩膀上,肯定会快很多。本次实践,虽然花了很多时间去解决问题,但是当看到执行结果是成功的时候,那种心情还是很激动的。

Demo下载:

参考地址:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值