常见的java调用python脚本方式
1.通过Jython.jar提供的类库实现
2.通过Runtime.getRuntime()开启进程来执行脚本文件
1.Jython
Jpython使用时,版本很重要!大多数坑来源于此。这句话不听的人还得走点弯路
运行环境:Python2.7 + Jython-standalone-2.7.0
<!--Maven依赖,jar包自行前往仓库下载-->
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.0</version>
</dependency>
1)Jython执行Python语句
import org.python.util.PythonInterpreter;
public class HelloPython {
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.exec("print('hello')");
}
}
2)Jython执行Python脚本
import org.python.util.PythonInterpreter;
public class HelloPython {
public static void main(String[] args) {
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.execfile("./pythonSrc/time.py");
}
}
3)Jython执行Python方法获取返回值
PythonInterpreter interpreter = new PythonInterpreter();
interpreter = new PythonInterpreter();
interpreter.execfile("./pythonSrc/fibo.py");
PyFunction function = (PyFunction)interpreter.get("fib",PyFunction.class);
PyObject o = function.__call__(new PyInteger(8));
System.out.println(o.toString());
fibo.py
# Fibonacci numbers module
def fib(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b ·
return result
2.Jython的局限
Jython在执行普通py脚本时速度很慢,而且在含有第三方库(requests, jieba…)时bug很多,不易处理。 原因在于,python执行时的sys.path和Jython的sys.path路径不一致,以及Jython的处理不是很好。
python执行时:
['F:\\Eclipse for Java EE\\workspace\\Jython\\pythonSrc', 'F:\\Python27\\DLLs', 'F:\\Python27\\lib', 'F:\\Python27\\lib\\lib-tk', 'F:\\Python27', 'F:\\Python27\\lib\\site-packages', 'F:\\Python27\\lib\\site-packages\\unknown-0.0.0-py2.7.egg', 'F:\\Python27\\lib\\site-packages\\requests-2.18.4-py2.7.egg', 'F:\\Python27\\lib\\site-packages\\certifi-2018.1.18-py2.7.egg', 'F:\\Python27\\lib\\site-packages\\urllib3-1.22-py2.7.egg', 'F:\\Python27\\lib\\site-packages\\idna-2.6-py2.7.egg', 'F:\\Python27\\lib\\site-packages\\chardet-3.0.4-py2.7.egg', 'C:\\windows\\system32\\python27.zip', 'F:\\Python27\\lib\\plat-win']
Jython 执行时:
['F:\\Maven\\repo\\org\\python\\jython-standalone\\2.7.0\\Lib', 'F:\\Maven\\repo\\org\\python\\jython-standalone\\2.7.0\\jython-standalone-2.7.0.jar\\Lib', '__classpath__', '__pyclasspath__/']
关于路径问题,我们有两种解决方法,一是手动添加第三方库路径,调用
PySystemState sys = Py.getSystemState();
System.out.println(sys.path.toString());
sys.path.add("F:\\Python27\\Lib\\site-packages\\jieba");
二是把第三方库文件夹放到执行的.py脚本同级目录。
然后新的问题来了,你以为路径是最终的问题吗?不止,也许是Python的版本语法问题,2x,3x,导致你在用Jython执行含第三方库的.py脚本时,各种Module不存在。原本博主走的Jython的路子,还下载了jieba第三方库,后来运行时一大堆错误:jieba库好像对py3有过渡支持,jython不支持这种语法格式,我改了jieba一处又一处,所以,博主在受过摧残之后果断放弃Jython!因为不能使用第三方库的python,然并卵!
最终方法来了:模拟控制台执行
public class Cmd {
public static void main(String[] args) throws IOException, InterruptedException {
String[] arguments = new String[] { "python", "./pythonSrc/time.py", "huzhiwei", "25" };
try {
Process process = Runtime.getRuntime().exec(arguments);
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
int re = process.waitFor();
System.out.println(re);
} catch (Exception e) {
e.printStackTrace();
}
}
}
time.py
#!/usr/bin/python
#coding=utf-8
#定义一个方法
def my_test(name, age):
print("name: "+str(name))
print(age) #str()防解码出错
return "success"
#主程序
#sys.argv[1]获取cmd输入的参数
my_test(sys.argv[1], sys.argv[2])
执行结果
name: huzhiwei
25
0
再唠两块钱的~
这个方法的局限性也来了,对python开发人员很简单,直接打印输出,但一个python模块只能做一件事,这点很像Python端给Java端的一个公开接口,很像Servlet吧?好处也有,不会出错,运行快!还在犹豫的同学赶快转cmd吧~!