在进行开发的过程中,偶尔会遇到需要使用Java调用Python脚本的时候,毕竟Python在诸如爬虫,以及科学计算等方面具有天然的优势。最近在工作中遇到需要在Java程序中调用已经写好的Python程序,故做一下记录。

1常用的Java调用Python脚本的两种方式

调用方式通常为以下两种:

•通过Jython调用,即通过Jython.jar提供的类库实现

•直接通过Java的Runtime实现,Runtime类的Runtime.getRuntime()开启进程,执行python脚本文件

2通过Jython实现调用

Jython简介

Jython主页:http://www.jython.org/

Jython是Python语言在Java平台的实现,本质上,Jython是由Java编写,其是在JVM上实现的Python语言。因此,可以直接通过Jython在Java中调用Python。

Jython安装

在安装Jython之前,必须确保本地已经安装了JDK。

1. 通过Jython的官网下载对应版本的安装文件Installer和单独的standalone jar两个jar文件,放到特定的目录下,如C:jython2.7.0;

2. 进入终端,切换到当前用于安装Jython的jar文件所在的目录下,执行java -jar jython_installer_2.7.0.jar,「当然也可以直接进入目录双击对应的jar文件进行安装」;

3. 配置对应的环境变量,分别将对应的jar,lib目录加到CLASSPATH和Path中:

–C:jython2.7.0jython.jar; 加入到CLASSPATH中

–C:jython2.7.0;C:jython2.7.0Lib;加入到Path中

此时在终端下执行jython命令,如果安装成功,则会进入到Jython的交互环境,可与Python的交互环境一样执行Python命令。同时也可以通过jython xxx.py命令执行python脚本文件。

Jython执行Python脚本

  • 直接在Java中嵌入Python语句

在Java中直接嵌入Python语句的用法较少,且实际意义不大。

import org.python.util.PythonInterpreter;

public class Main {

public static void main(String[] args) {

PythonInterpreter interpreter = new PythonInterpreter();

//执行Python语句

interpreter.exec("import sys");

interpreter.exec("print 'hello'");

interpreter.exec("print 2**100");

}

}

  • 在Java中执行已经编写好的名为xxx.py的 Python脚本

直接通过Jython包调用写好的Python脚本,根据程序执行时的要求,大体可以分为以下几种情况:

1.不需要通过Java程序向Python脚本中传递参数,也不需要获取Python脚本之行后的返回值,则可以通过文件流的方式直接打开脚本,并使用Jython的解释器执行。

import org.python.util.PythonInterpreter;

import java.io.*;

public class Main {

public static void main(String[] args) {

PythonInterpreter interpreter = new PythonInterpreter();

//执行Python脚本文件

try {

InputStream filepy = new FileInputStream("C:xxx.py");

interpreter.execfile(filepy);

filepy.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

2.在Java中调用Python程序,同时需要传递参数和接收返回值。调用Python程序中的方法,可分为两种,一种是直接调用Python中写好的方法函数,另一种则是调用Python脚本的类中的函数。

–直接调用函数,通过PyFunction实现参数的传递和返回值的获取

import org.python.core.*;

import org.python.util.PythonInterpreter;

public class Main{

public static void main(String[] args) {

PythonInterpreter inter = new PythonInterpreter();

//指定Python函数文件的路径

String pythonFunc = "D:test.py";

inter.execfile(pythonFunc);

//获取函数名test

PyFunction pyf = inter.get("test", PyFunction.class);

//向函数中传递参数并获取返回结果

PyObject res = pyf.__call__(Py.newInteger(2), Py.newInteger(3));

System.out.print(res);

inter.cleanup();

inter.close();

}

}

– 在Java中调用Python对象实例方法,使用PyObject方法实例化Python对象,调用Python对象方法,传递参数并切接收返回值。

import org.python.core.*;

import org.python.util.PythonInterpreter;

public class Main{

public static void main(String[] args) {

PythonInterpreter inter = new PythonInterpreter();

//python类路径

String pythonClass = "D:test_class.py";

//python 对象名

String pythonObjName = "cal";

// python类名

String pythonClazzName = "Calculator";

inter.execfile(pythonClass);

//实例化Python对象

inter.exec(PythonObjName + "=" + pythonClazzName + "()");

//获取实例化的Python对象

PyObject pyObject = inter.get(pythonObjName);

//调用python对象方法,传递参数并接收返回值

PyObject res = pyObject.invoke("power", new PyObject[] {Py.newInteger(2), Py.newInteger(3)});

double power = Py.py2double(res);

System.out.print(power);

inter.cleanup();

inter.close();

}

}

其中,test_class.py文件的内容如下:

import math

class Calculator(object):

def power(x, y):

return math.pow(x, y)

  • 通过Runtime.getRuntime().exec()实现调用

Runtime类是Java中一个与JVM运行时环境有关的类,通过Runtime.getRuntime()可以获取到当前JVM运行时的环境。Runtime上的大部分方法都是实例方法,即每次在进行运行时调用时都要用到getRuntime()方法。使用Runtime类执行Python脚本的方法非常简单粗暴,直接传入当前平台下的Python脚本执行命令即可。Java执行外部命令,主要方式还是使用Runtime类的exec()方法调用平台shell完成,如windows下的cmd,以及linux、unix、macOS下的的shell。

通过Runtime执行Python脚本,可以直接通过命令向脚本中传递参数,并获取Python脚本的输出。

public class Main{

public static void main(String[] args) {

String cmd = "python xxx.py argv1 argv2 ...";

Process proc = Runtime.getRuntime().exec(cmd);

InputStream is = proc.getInputStream();

DataInputStream dis = new DataInputStream(is);

String str = dis.readLine();

proc.waitFor();

System.out.println(str);

}

}

3总结

以上两种方法都可以实现在Java程序中调用Python脚本,但使用Jython进行调用时,效率较低,也会消耗较多资源,且调用的脚本需要Python的第三方依赖包时,需要在Jython中安装第三方包。而使用Runtime调用脚本时,更多的依赖于运行的平台,只要当前平台安装了对应的第三方依赖包,脚本就可以顺利执行,执行效率和直接执行Python脚本并没有区别。

当然,在程序中不断的进行嵌套调用,会降低程序的执行效率,增加程序的耦合复杂度,不方便将来的扩展,因此并不建议大家经常使用,而可以考虑通过微服务的方法解决对应的问题。

文章还有很多不足之处,希望大家多多交流,多多指教。

参考链接

1.五大基于JVM的脚本语言https://coolshell.cn/articles/2631.html

2.Java调用Python http://tonl.iteye.com/blog/1918245

3.Java Runtime.exec()的使用https://blog.csdn.net/toneylyx/article/details/52623597

4.Why are there so many pythons https://www.oschina.net/translate/why-are-there-so-many-pythons

5.Jython www.jython.org

通过Java调用Python脚本的更多相关文章

  1. java调用python脚本并向python脚本传递参数

    1.安装Eclipse 先安装jdk,再安装Eclipse,成功后开始建立py_java项目,在这个项目的存储目录SRC下建立test包,在test包中New-Class,新建MyDemo类,建好完成 ...

  2. (转)java调用python脚本

    这篇博客旨在吐血分享今天遇到的java调用python脚本遇到的坑,折腾了3个多小时终于可以跑通了,代码超级短,但网上的好多资料都是抄来抄去的,很少有能够直接跑通的,尤其是针对你的python文件中用 ...

  3. [Java/Python] java调用python脚本问题记录

    Java调用Python的的两种方式 1.Runtime private static String call_python(String input_argv) { String python_py ...

  4. Java调用Python脚本并获取返回值

    在Java程序中有时需要调用Python的程序,这时可以使用一般的PyFunction来调用python的函数并获得返回值,但是采用这种方法有可能出现一些莫名其妙的错误,比如ImportError.在 ...

  5. Java调用Python脚本

    今天遇到Java调用一个Python脚本的问题,纠结了大半天,遇到各种问题.网上搜索的大部分都是用jython,但是我想要调用的python脚本里有import urllib,这个urllib也不是什 ...

  6. java 调用 python 脚本

    有时候在java项目里,需要执行Python脚本以下几种方式: 1.直接执行Python脚本代码 引用 org.python包 创建一个 python解释器,貌似这种方式不可以导入第三方库,模块... ...

  7. Java调用Python脚本工具类

    [本文出自天外归云的博客园] 在网上查了很多方法都不成功,在google上搜到一篇文章,做了一些小修改,能够处理中文输出.提取一个运行python脚本的Java工具类如下: package com.a ...

  8. Java 调用python说明文档

    Java 调用python说明文档 通过java调用python脚本主要如下三种方式: 1.直接执行python脚本: 2.执行python.py文件: 3.使用Runtime.getRuntime( ...

  9. java中怎么调用python 脚本

    调用方法: import java.io.BufferedReader; import java.io.InputStreamReader; public class PythonInvoke { p ...

随机推荐

  1. 【miscellaneous】各种音视频编解码学习详解

    编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放license收费等等 ...

  2. linux 安装了Linux generic mysql 出错

    在一次安装 Linux generic cmake 出错 提示:CMake Error: The source directory "/usr/local/src" does no ...

  3. UIPath工具取得某个路径下的文件夹的名称

    UIPath工具取得某个路径下的文件夹的名称 处理的流程如下图 [Edit Code]按钮押下之后写入代码如下 Dim dir As New DirectoryInfo("C:\Users\ ...

  4. django授权-01--oauth2

    oauth2的提供商:认证服务器 oauth2的消费者:目标服务器 如果目标服务器与认证服务器不一样的话,相当于目标服务器向认证服务器获取用户的信息 如果目标服务器和认证服务器一样的话,相当于用户获取 ...

  5. 《Mysql - 我的Mysql为什么会抖一下?》

    一: 抖一下? - 平时的工作中,不知道有没有遇到过这样的场景. - 一条 SQL 语句,正常执行的时候特别快,但是有时也不知道怎么回事,它就会变得特别慢. - 并且这样的场景很难复现,它不只随机,而 ...

  6. Python 安装包时选择 python版本

    安装了两个版本的python 其中一个版本为2.7 专门为python 2.7安装包使用的语句为 升级pip E:\Python27\python -m pip install --upgrade p ...

  7. 使用RabbitMQ实现分布式事务

    RabbitMQ解决分布式事务思路: 案例: 经典案例,以目前流行点外卖的案例,用户下单后,调用订单服务,让后订单服务调用派单系统通知送外卖人员送单,这时候订单系统与派单系统采用MQ异步通讯. Rab ...

  8. Mysql的实现原理

    上篇文章已经简单介绍了Mysql索引的基本介绍,这篇文章主要讲解一下所以的实现原理.索引的定义其实非常复杂,严格的定义需要用到关系代数的概念,不在咱们讨论范围内,这里咱们只讨论mysql的常用的引擎的 ...

  9. js中WebSocket

    一.概念 WebSocket的定义 WebSocket是html5提供的一种在单个TCP连接上进行双向通信的协议,解决了客户端和服务端之间的实时通信问题.浏览器和服务器只需完成一次握手,两者之间就可以 ...

  10. .net Core如何对静态文件的访问进行鉴权操作?

    之前给公司开发了一个文件管理服务,最基本的功能就是文件的上传下载,以及更新删除.预览:负责公司各个子系统的相关附件的管理,所有的接口都通过AOP来进行身份拦截认证了,但是在进行预览的时候,因为采用的是 ...