骚操作 !Java 中调用 Python,动态传入参数 !
点击关注公众号,Java干货及时送达👇
目录
- 一、前言
- 二、Jython 官网地址
- 三、上手试试
- 添加依赖
- 测试执行 Python
- 在 Java 类中直接执行 Python 语句
- 在 Java 中调用 Python 脚本文件
- 另外一种方式:
Runtime.getRuntime()
执行 python 脚本文件 - 调用 Python 脚本发送邮件,并动态传入参数,打印结果
- 四、结语
一、前言
大家好,我是小哈~
今天给大家分享一下如何在 Java 中执行 Python 脚本,这种需求,小哈在以前参与的定时任务调度平台就遇到过,需要定时去触发某个作业,作业需要支撑业务线丰富的场景,可以是接口调用、Shell 脚本执行、推送 MQ、Python 脚本执行等。
除此以外,大家都知道 Python 拥有非常丰富的第三方类库,有些功能用 Python 来实现的话,可能仅仅需要引入一下包,几行代码就搞定了,用 Java 来实现可能就需要费老鼻子劲了。
好了,废话也不多说,进入今天的正题 !
给大家安利一个优秀的第三方库 Jython
, 通过它可以非常方便的执行 Python 脚本。
二、Jython 官网地址
官网地址:https://www.jython.org/
Github 地址:https://github.com/jython/jython
三、上手试试
小哈为了给大家演示,先新建一个 Spring Boot 项目。
3.1 添加依赖
在 maven 的 pom.xml
中添加 Jython
依赖:
org.python
jython-standalone
2.7.2
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);
}
输出:
通过Jython执行一条简单的python语句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 的:
在java中执行python脚本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));
}
执行一下,你会发现报错:
jython调用python脚本的函数Python 脚本在没有指定具体编码时,默认以 ASCII
编码,这里因为文件中涉及到中文,需要指定编码格式为 utf-8
, 在脚本文件头添加如下代码:
# -*- coding: utf-8 -*-
在python文件头部指定编码格式PS: 详细参考:https://peps.python.org/pep-0263/
再次执行看看:
python发送邮件结果成功打印了返回参数,确认一下是否真的收到邮件了:
邮件接受成功成功收到了邮件。
细心的小伙伴应该发现了,在控制台打印中有个 500
错误,提示内容被拒绝了,但确实又收到了邮件,这是个啥情况,点进后面的连接看了一下 http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=20022&&no=1000726:
初步怀疑是自己做测试发送了过多的邮件导致,被 QQ 判定为垃圾营销邮件了,但是收还是能收到的,小伙伴们如果收不到也可以将发送者的邮箱地址设置为 QQ 邮件白名单。
四、结语
小伙伴们如果有需要在 Java 中执行 Python 脚本的,不妨试试 Jython
这个库,整体来说还是非常棒滴~ 这期分享就到这里了,下期见~
文章首发自个站:犬小哈教程
https://www.quanxiaoha.com/article/java-invoke-python-by-jython.html
五、Ref
https://www.cnblogs.com/wuwuyong/p/10600749.html
https://blog.csdn.net/qq_26591517/article/details/80441540
最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。
PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。
点“在看”支持小哈呀,谢谢啦😀