怎么制作网站商城,上海网站排名公司,东莞哪家公司做网站比较好,网站网络推广企业写在前面
在微服务架构大行其道的今天#xff0c;对于将程序进行嵌套调用的做法其实并不可取#xff0c;甚至显得有些愚蠢。当然#xff0c;之所以要面对这个问题#xff0c;或许是因为一些历史原因#xff0c;或者仅仅是为了简单。恰好我在项目中就遇到了这个问题#…写在前面
在微服务架构大行其道的今天对于将程序进行嵌套调用的做法其实并不可取甚至显得有些愚蠢。当然之所以要面对这个问题或许是因为一些历史原因或者仅仅是为了简单。恰好我在项目中就遇到了这个问题需要在Java程序中调用Python程序。关于在Java中调用Python程序的实现根据不同的用途可以使用多种不同的方法在这里就将在Java中调用Python程序的方式做一个总结。
直接通过Runtime进行调用
我们知道在Java中如果需要调用第三方程序可以直接通过Runtime实现这也是最直接最粗暴的做法。
public class InvokeByRuntime {/*** param args* throws IOException * throws InterruptedException */public static void main(String[] args) throws IOException InterruptedException {String exe python;String command D:\\calculator_simple.py;String num1 1;String num2 2;String[] cmdArr new String[] {exe command num1 num2};Process process Runtime.getRuntime().exec(cmdArr);InputStream is process.getInputStream();DataInputStream dis new DataInputStream(is);String str dis.readLine();process.waitFor();System.out.println(str);}
}输出
3calculator_simple.py:
# codingutf-8
from sys import argvnum1 argv[1]
num2 argv[2]
sum int(num1) int(num2)
print sum显然在Java中通过Runtime调用Python程序与直接执行Python程序的效果是一样的可以在Python中读取传递的参数也可以在Java中读取到Python的执行结果。需要注意的是不能在Python中通过return语句返回结果只能将返回值写入到标准输出流中然后在Java中通过标准输入流读取Python的输出值。
通过Jython调用
通过Jython调用Python我在听到这个概念的时候一脸懵逼不是说好的在Java中调用Python程序吗这个Jython是什么鬼难道是一个在Java中调用Python程序的组件或工具其实关于Jython是什么这个疑问我估计有许多人在一开始接触的时候也是很疑惑的下面我们就一一道来。
1. 什么是Jython
Jython主页http://www.jython.org/currentdocs.html 按照官方的定义Jython是Python语言在Java平台的实现。这个概念似乎有点拗口反正我一开始并没有理解。Python难道不已经是一门语言了吗什么叫做Jython是Python语言在Java平台的实现 实际上之所以存在这样的困惑主要是因为我们对Python语言的相关概念掌握和理解不清楚导致的。 Python其实只是一个语言规范它存在多个不同语言实现的版本。具体来说目前Python语言存在如下几个具体实现 1CPythonCPython是标准Python也是其他Python编译器的参考实现。通常提到“Python”一词都是指CPython。CPython由C编写将Python源码编译成CPython字节码由虚拟机解释执行。没有用到JIT等技术垃圾回收方面采用的是引用计数。 2JythonJython是在JVM上实现的Python由Java编写。Jython将Python源码编译成JVM字节码由JVM执行对应的字节码。因此能很好的与JVM集成比如利用JVM的垃圾回收和JIT直接导入并调用JVM上其他语言编写的库和函数。 3IronPythonIronPython与Jython类似所不同的是IronPython在CLR上实现的Python即面向.NET平台由C#编写。IronPython将源码编译成TODO CLR同样能很好的与.NET平台集成。即与Jython相同可以利用.NET框架的JIT、垃圾回收等功能能导入并调用.NET上其他语言编写的库和函数。IronPython默认使用Unicode字符串。 4PyPy这里说的PyPy是指使用RPython实现利用Tracing JIT技术实现的Python而不是RPython工具链。PyPy可以选择多种垃圾回收方式如标记清除、标记压缩、分代等。 5PystonPyston由Dropbox开发使用C11编写采用Method-at-a-time-JIT和Mark Sweep——Stop the World的GC技术。Pyston使用类似JavaScript V8那样的多层编译其中也用到了LLVM来优化代码。
所以我们现在再来理解什么是Jython就非常清楚了Jython是Python语言规范在Java平台的具体实现。具体来说可以将Python源码编译为JVM可以解释执行的字节码。 Jython原本叫做JPython于1997年由Jim Hugunin创建后来在1999年2.0版本发布的时候由Barry Warsaw更名为Jython在这里我们就不再深究为什么要把JPython更名为Jython的原因了。注意 Jython从2.0版本开始就与CPython的版本保持一致即Jython 2.7与CPython 2.7保持对应。
虽然我们理解了什么是Jython但是还存在一个疑问为什么Python语言存在这么多不同语言的实现呢为什么不能就只存在一个C语言实现的版本就可以了呢存在这么多版本真的给初学者带来了许多困惑。 当然要回答这个问题可能就需要深究一些历史的原因了就此打住。我们在此只讨论使用Jython能做什么以及如何使用Jython
2. 使用Jython能做什么
既然Jython是Python语言在Java平台的实现是Java语言实现的那么是否可以在Jython程序中调用Java在Java中也能调用Jython呢 答案是肯定的实际上Jython的主要通途就是在Java中调用Python程序而且还可以直接在Jython程序中引用Java。
3. 如何使用Jython
3.1 安装Jython
在Jython的官方下载页面我们可以看到如下描述详见http://www.jython.org/downloads.html 显然可以下载2个Jython的jar包。其中jython-installer-${version}.jar是用于安装Jython的jython-standalone-${version}.jar用于嵌入到Java程序中使用。 什么意思我一开始也是很疑惑为什么要提供2个不同的jar包呢他们有什么不同呢2个不同的Jar包如何使用呢 首先jython-installer-${version}.jar用于安装Jython就好比我们需要安装JRE用于运行Java程序。除此之外当需要在Python程序中引用一些公共的第三方库时也需要先安装Jython才能下载所依赖的模块。
下载jython-installer-${version}.jar完毕之后进入控制台执行如下命令
java -jar jython-installer-${version}.jar此时会弹出一个图形化的安装界面只需要一步一步选择相应参数进行安装即可。安装完毕之后请将Jython安装目录添加为环境变量JYTHON_HOME同时添加bin目录到PATH变量中PATH$PATH:$JYTHON_HOME/bin。 进入控制台执行如下命令就可以进入Jython的交互环境这与CPython我们通常说的Python的命令行交互环境是一样的。 jython
Jython 2.7.0 (default:9987c746f838 Apr 29 2015 02:25:11)
[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.8.0_121
Type help copyright credits or license for more information.print(helloworld)
helloworld当然我们还可以使用jython命令运行一个Python程序。 jython helloworld.py
helloworldhelloworld.py:
import sysprint(helloworld)上面我们看到在Jython官网提供了2个Jar包一个用于安装Jython执行Python程序。那么jython-standalone-${version}.jar又有什么用途呢 实际上当我们需要在Java中调用Python程序时除了直接使用Java的Runtime调用还可以直接使用Jython的API进行调用而且通过Jython API可以直接调用Python程序中的指定函数或者对象方法粒度更加精细。 当我们需要调用Jython的API时有两种方式 第一如果项目使用Maven进行构建可以直接添加Jython的依赖配置到pom.xml文件中如
dependencygroupIdorg.python/groupIdartifactIdjython/artifactIdversion2.7.0/version
/dependency第二可以直接将jython-standalone-${version}.jar添加到项目classpath中这样也可以调用Jython的相关API了。也就是说jython-standalone-${version}.jar就是一个提供Jython API的jar独立jar包。
3.2 Java调用Python程序实践
Java通过Jython API调用Python程序有几种用法 1在Java中执行Python语句相当于在Java中嵌入了Python程序这种用法不常见也没有太大的实际意义。
public static void main(String[] args) {System.setProperty(python.home D:\\jython2.7.0);PythonInterpreter interp new PythonInterpreter();// 执行Python程序语句interp.exec(import sys);interp.set(a new PyInteger(42));interp.exec(print a);interp.exec(x 22);PyObject x interp.get(x);System.out.println(x: x);
}输出
42
x: 42在Java中简单调用Python程序不需要传递参数也不需要获取返回值。
public static void main(String[] args) throws IOException {System.setProperty(python.home D:\\jython2.7.0);String python D:\\simple_python.py;PythonInterpreter interp new PythonInterpreter();interp.execfile(python);interp.cleanup();interp.close();
}simple_python.py:
# codingutf-8
print(Do simple thing in Python)
print(输出中文)3在Java中单向调用Python程序中的方法需要传递参数并接收返回值。Python既支持面向函数式编程也支持面向对象编程。因此调用Python程序中的方法也分别以面向函数式编程和面向对象式编程进行说明。
public static void main(String[] args) throws IOException {System.setProperty(python.home D:\\jython2.7.0);// 1. Python面向函数式编程: 在Java中调用Python函数String pythonFunc D:\\calculator_func.py;PythonInterpreter pi1 new PythonInterpreter();// 加载python程序pi1.execfile(pythonFunc);// 调用Python程序中的函数PyFunction pyf pi1.get(power, PyFunction.class);PyObject dddRes pyf.__call__(Py.newInteger(2), Py.newInteger(3));System.out.println(dddRes);pi1.cleanup();pi1.close();// 2. 面向对象式编程: 在Java中调用Python对象实例的方法String pythonClass D:\\calculator_clazz.py;// python对象名String pythonObjName cal;// python类名String pythonClazzName Calculator;PythonInterpreter pi2 new PythonInterpreter();// 加载python程序pi2.execfile(pythonClass);// 实例化python对象pi2.exec(pythonObjName pythonClazzName ());// 获取实例化的python对象PyObject pyObj pi2.get(pythonObjName);// 调用python对象方法,传递参数并接收返回值PyObject result pyObj.invoke(power, new PyObject[] {Py.newInteger(2), Py.newInteger(3)}); double power Py.py2double(result);System.out.println(power);pi2.cleanup();pi2.close();
}输出
8.0
8.0calculator_func.py
# codingutf-8
import math# 面向函数式编程
def power(x, y):return math.pow(x, y)calculator_clazz.py
# codingutf-8
import math# 面向对象编程
class Calculator(object):# 计算x的y次方def power(self, x, y):return math.pow(x,y)4高级调用也是在Java中调用Python程序最常见的用法Python程序可以实现Java接口在Python中也可以调用Java方法。
public static void main(String[] args) throws IOException {System.setProperty(python.home D:\\jython2.7.0);// Python程序路径String python D:\\python\\fruit_controller.py;// Python实例对象名String pyObjName pyController;// Python类名String pyClazzName FruitController;Fruit apple new Apple();Fruit orange new Orange();PythonInterpreter interpreter new PythonInterpreter();// 如果在Python程序中引用了第三方库,需要将这些被引用的第三方库所在路径添加到系统环境变量中// 否则,在执行Python程序时将会报错: ImportError: No module named xxxPySystemState sys interpreter.getSystemState();sys.path.add(D:\\python);// 加载Python程序interpreter.execfile(python);// 实例 Python对象interpreter.exec(pyObjName pyClazzName ());// 1.在Java中获取Python对象,并将Python对象转换为Java对象// 为什么能够转换? 因为Python类实现了Java接口,通过转换后的Java对象只能调用接口中定义的方法GroovyController controller (GroovyController) interpreter.get(pyObjName).__tojava__(GroovyController.class);controller.controllFruit(apple);controller.controllFruit(orange);// 2.在Java直接通过Python对象调用其方法// 既可以调用实现的Java接口方法,也可以调用Python类自定义的方法PyObject pyObject interpreter.get(pyObjName);pyObject.invoke(controllFruit, Py.java2py(apple));pyObject.invoke(controllFruit, Py.java2py(orange));pyObject.invoke(printFruit, Py.java2py(apple));pyObject.invoke(printFruit, Py.java2py(orange));// 3.在Java中获取Python类进行实例化对象: 没有事先创建 Python对象PyObject pyClass interpreter.get(FruitController);PyObject pyObj pyClass.__call__();pyObj.invoke(controllFruit, Py.java2py(apple));pyObj.invoke(controllFruit, Py.java2py(orange));PyObject power pyObj.invoke(power, new PyObject[] {Py.newInteger(2), Py.newInteger(3)});if(power ! null) {double p Py.py2double(power);System.out.println(p);}interpreter.cleanup();interpreter.close();
}输出
Show: I am a java apple.
controllFruit Python Apple
controllFruit END
Show: I am a java orange.
controllFruit Python Orange
controllFruit END
Show: I am a java apple.
controllFruit Python Apple
controllFruit END
Show: I am a java orange.
controllFruit Python Orange
controllFruit END
Show: I am a java apple.
printFruit Python Apple
printFruit END
Show: I am a java orange.
printFruit Python Orange
printFruit END
Show: I am a java apple.
controllFruit Python Apple
controllFruit END
Show: I am a java orange.
controllFruit Python Orange
controllFruit END
8.0fruit_controller.py
# codingutf-8from calculator_clazz import Calculator
from java.lang import String
from org.test.inter import GroovyController
from org.test.inter import Fruit# 在Python中实现Java接口: org.test.inter.GroovyController
class FruitController(GroovyController):# 实现接口方法def controllFruit(self, fruit):# 在Python中调用Java对象方法fruit.show()if(fruit.getType() apple):print (controllFruit Python Apple)if(fruit.getType() orange):print (controllFruit Python Orange)print (controllFruit END)# 自定义新方法 def printFruit(self, fruit):fruit.show()if(fruit.getType() apple):print (printFruit Python Apple)if(fruit.getType() orange):print (printFruit Python Orange)print (printFruit END)# 引用第三方python程序def power(self, x, y):cal Calculator()return cal.power(x, y)Java接口和实现类
// 该接口用于在Python中实现
public interface GroovyController {public void controllFruit(Fruit fruit);
}// 在Java中使用的接口
public interface Fruit {public String getName();public String getType();public void show();
}// Apple
public class Apple implements Fruit {public String getName() {return java apple;}public String getType() {return apple;}public void show() {System.out.println(Show: I am a java apple.);}
}// Orange
public class Orange implements Fruit {public String getName() {return ava orange;}public String getType() {return orange;}public void show() {System.out.println(Show: I am a java orange.);}另外对于在eclipse中运行时控制台报错
Failed to install : java.nio.charset.UnsupportedCharsetException: cp0请添加VM参数-Dpython.console.encodingUTF-8详见jython在eclipse控制台出现Failed to install ‘’: java.nio.charset.UnsupportedCharsetException: cp0解决方法_北一-CSDN博客