前段时间遇到了在JavaWeb项目中嵌入运行Python脚本的功能的需求。想到的方案有两种,一种是使用Java技术(Jython或Runtime.exec)运行Python脚本,另一种是搭建一个Python工程对外提供相应http或webservice接口。两种方案我都有实现,简单的测试了一下,本机环境两者的执行效率没有太大的差距。考虑到项目的情况,最终选择了第一种方案。
闲话少说,我们赶紧看看Java怎么实现运行Python脚本的吧~
Jython实现
简单来说,我们常说的Python是指CPython,由C语言编写。而这里说的Jython是由Java编写,在JVM中运行。显然,Jython天然就对Java有很高的亲和度(本身就是Java写的),能够利用JVM相关的技术,库和函数等资源。
Jython从2.0版本开始就和Python的版本保持一致,目前最新的版本为2.7.2。Jython的官方下载网址:https://www.jython.org/download。网址中有两个下载包Jython Installer、Jython Standalone。Jython Installer类似一个应用程序(exe),双击安装即可在cmd中使用Jython;而Jython Standalone可以作为jar包直接引入到项目中使用。对于项目编程,直接引入Maven依赖即可。
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.1</version>
</dependency>
注意:引用的不是org.python.jython,这将会产生一堆疑难杂症。引入的是jython-standalone,这是专门给java调用jython的包,有较多的jar库支持。
Jython运行Python脚本
Jython主要是使用PythonInterpreter类,调用方法大致有两种形式。
面向函数调用
根据需要调用的方法名获取对应的PyFunction对象,调用__call__方法获取方法的返回值。
在这种调用方式下,python脚本里面是定义了一些函数,且用Jython调用的时候,需要知道所要调用函数的名称。比如python脚本为:
# coding=utf-8
def main(str):
print(str)
那么java的关键代码如下:
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec(script);
// python脚本中的方法名为main
PyFunction function = interpreter.get("main",PyFunction.class);
// 将参数代入并执行python脚本
PyObject o = function.__call__(Py.newString(params));
面向对象调用
另外一种调用方式是,Python脚本是定义了一个类。可以通过类名获取对应的python对象,再用该对象调用类中定义的方法获取返回值。比如python脚本为:
# coding=utf-8
class Test(object):
def main(self,str):
print(str)
那么java的关键代码如下:
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec(script);
// 获取Python对象
PyObject pyObject = interpreter.get("Test");
// 调用方法,方法名为main。将参数代入并执行python脚本,获取返回值
// 传入参数对象的个数要与调用的方法一致
PyObject o= pyObj.invoke("main",new PyObject[]{
Py.newString(params)}));
引入第三方包
Python作为最流行的开源编程语言之一,拥有广泛的第三方包,应该说当下的Python编程已无法离开这丰富的第三方包的支持。Jython本身也包含较多的jar包支持日常的编程,同时也支持引入第三方包。引入的方式如下两种,第一种是引入Jython本身提供的jar包:以引入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();
第二种可以直接指定引入的第三方包所在的目录:
PythonInterpreter interpreter = new PythonInterpreter();
PySystemState sys = interpreter.getSystemState();
sys.path.add("C:/jython2.7.1/Lib");
第二种方法有另一种写法:
PythonInterpreter interpreter =