Java 如何调用执行 Python?图文讲解超详细!
一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ; - 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 66w+ 字,讲解图 2896+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2300+ 小伙伴加入学习 ,欢迎点击围观
目录
- 一、前言
- 二、Jython 官网地址
- 三、上手试试
- 添加依赖
- 测试执行 Python
- 在 Java 类中直接执行 Python 语句
- 在 Java 中调用 Python 脚本文件
- 另外一种方式:
Runtime.getRuntime()
执行 python 脚本文件 - 调用 Python 脚本发送邮件,并动态传入参数,打印结果
- 四、结语
一、前言
大家好,我是小哈~
今天给大家分享一下如何在 Java 中执行 Python 脚本,这种需求,小哈在以前参与的定时任务调度平台就遇到过,需要定时去触发某个作业,作业需要支撑业务线丰富的场景,可以是接口调用、Shell 脚本执行、推送 MQ、Python 脚本执行等。
除此以外,大家都知道 Python 拥有非常丰富的第三方类库,有些功能用 Python 来实现的话,可能仅仅需要引入一下包,几行代码就搞定了,用 Java 来实现可能就需要费老鼻子劲了。
好了,废话也不多说,进入今天的正题 !
给大家安利一个优秀的第三方库 Jython
, 通过它可以非常方便的执行 Python 脚本。
二、Jython 官网地址
Github 地址: https://github.com/jython/jython
三、上手试试
小哈为了给大家演示,先新建一个 Spring Boot 项目。
3.1 添加依赖
在 maven 的 pom.xml
中添加 Jython
依赖:
<dependency>
<groupId>org.python</groupId>
<artifactId>jython-standalone</artifactId>
<version>2.7.2</version>
</dependency>
3.2 测试执行 Python
注意,需要在你的机器上先安装好 Python 环境。
3.2.1 在 Java 类中直接执行 Python 语句
新建单元测试,通过 Java 代码直接执行 Python 语句:
@Test
void executePython() {
// 一条简单的 python 语句,打印 Hello world !
String py = "print('Hello world!')";
PythonInterpreter interpreter = new PythonInterpreter();
// 执行 Python 语句
interpreter.exec(py);
}
输出:
3.2.2 在 Java 中调用 Python 脚本文件
大多数情况下,需要执行的是具体目录下的 Python 脚本,为了测试,我们在 D
盘的根目录下新建 test.py
,将刚刚的 Hello world
代码以文件的形式来运行:
通过 Jython 去执行这个脚本:
@Test
void executePythonFile() {
// 定义脚本路径
String path = "D:\\test.py";
PythonInterpreter interpreter = new PythonInterpreter();
// 执行脚本文件
interpreter.execfile(path);
}
可以看到,执行 Python 脚本也是 ok 的:
3.2.3 另外一种方式: Runtime.getRuntime()
执行 python 脚本文件
还是刚刚的测试脚本,还可以通过 Runtime.getRuntime()
来执行, 示例代码如下:
@Test
void executePythonFile2() {
Process proc;
BufferedReader reader;
try {
// 直接执行 python 命令的方式来执行脚本
proc = Runtime.getRuntime().exec("python D:\\test.py");
reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
// 打印输出
System.out.println(line);
}
reader.close();
proc.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
输出结果同上。
3.2.4 调用 Python 脚本调用某个函数,并动态传入参数,打印结果
实际的业务场景中,我们可能需要在调用脚本文件时动态传入参数,并打印结果。这里为了测试,小哈简单写了个发送邮件的 Python 脚本,定义了一个 sendEmail
函数,需要传入以下 3 个参数:
- 邮件接受者:
receiver
- 邮件标题:
subject
- 邮件内容:
content
代码如下:
import smtplib
from email.mime.text import MIMEText
# 邮件服务器地址
mail_host = 'smtp.qq.com'
# 邮件服务器用户名
mail_user = 'xxx@qq.com'
# 邮件服务器登录密码(有些是授权码)
mail_pwd = 'xxx'
# 邮件发送者
sender = 'xxx@qq.com'
def sendEmail(receiver, subject, content):
"""
发送邮件
:param receiver: 接收者
:param subject: 邮件主题
:param content: 邮件内容
:return:
"""
message = MIMEText(content, 'plain', 'utf-8')
# 邮件主题
message['Subject'] = subject
# 发送方
message['From'] = sender
# 接收方
message['To'] = receiver
try:
# 连接到服务器
smtp = smtplib.SMTP_SSL(mail_host)
# 登录服务器
smtp.login(mail_user, mail_pwd)
# 发送
smtp.sendmail(sender, receiver, message.as_string())
# 推出
smtp.quit()
return 'send email success ...'
except smtplib.SMTPException as e:
print('error', e)
if __name__ == '__main__':
# 邮件接受者
receiver = 'xxx@qq.com'
# 邮件主题
subject = '打个招呼'
# 邮件内容
content = '我是犬小哈'
sendEmail(receiver, subject, content)
代码中使用的是 QQ 邮件,邮件服务器的用户名和授权码就不放出来了,有兴趣的小伙伴,可将其替换自己的试试。
再来看看如何通过 Jython 去调用 sendEmail
函数:
@Test
void executePythonFunction() {
PythonInterpreter interpreter = new PythonInterpreter();
// 指定指定路径下的 python 脚本
interpreter.execfile("D:\\test.py");
// 指定需要调用的函数
PyFunction function = interpreter.get("sendEmail", PyFunction.class);
// ↓↓↓↓↓↓↓↓ 需要传入的参数 ↓↓↓↓↓↓↓↓
// 邮件接受者
PyString receiver = Py.newStringOrUnicode("xxx@qq.com");
// 邮件主题
PyString subject = Py.newStringOrUnicode("打个招呼【动态参数】");
// 邮件内容
PyString content = Py.newStringOrUnicode("我是犬小哈【动态参数】");
// 调用
PyObject pyObject = function.__call__(receiver, subject, content);
// 打印返回结果
System.out.println(String.format("result: %s", pyObject));
}
执行一下,你会发现报错:
Python 脚本在没有指定具体编码时,默认以 ASCII
编码,这里因为文件中涉及到中文,需要指定编码格式为 utf-8
, 在脚本文件头添加如下代码:
# -*- coding: utf-8 -*-
PS: 详细参考:https://peps.python.org/pep-0263/
再次执行看看:
成功打印了返回参数,确认一下是否真的收到邮件了:
成功收到了邮件。
细心的小伙伴应该发现了,在控制台打印中有个 550
错误,提示内容被拒绝了,但确实又收到了邮件,这是个啥情况,点进后面的连接看了一下 http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=20022&&no=1000726:
初步怀疑是自己做测试发送了过多的邮件导致,被 QQ 判定为垃圾营销邮件了,但是收还是能收到的,小伙伴们如果收不到也可以将发送者的邮箱地址设置为 QQ 邮件白名单。
四、结语
小伙伴们如果有需要在 Java 中执行 Python 脚本的,不妨试试 Jython
这个库,整体来说还是非常棒滴~ 这期分享就到这里了,下期见~
五、Ref
-
https://www.cnblogs.com/wuwuyong/p/10600749.html
-
https://blog.csdn.net/qq_26591517/article/details/80441540