Python 实用工具:py4j 从入门到实战,轻松实现 Python 与 Java 互操作

一、py4j 库概述

py4j 是一款专注于Python 与 Java 双向通信、互操作的开源库,能够让 Python 代码直接调用 Java 对象、方法,也可让 Java 调用 Python 代码,基于 Socket 通信实现跨语言交互,无需额外编译。其采用 BSD 开源许可,使用灵活无商业限制。优点是接入简单、无侵入、支持完整 Java 生态,缺点是依赖网络通信,存在少量性能开销,不适合超高频低延迟场景。

二、py4j 核心工作原理

py4j 本质是一套跨语言的 RPC 通信框架,核心运行流程分为两步:

  1. 启动 Java 端的 GatewayServer 网关服务,监听指定端口,作为通信桥梁;
  2. Python 端通过 GatewayClient 连接该服务,借助协议解析,把 Python 调用转为 Java 指令执行,再把结果返回 Python。

整个过程对开发者透明,无需关心底层序列化、网络传输,只需像调用本地代码一样使用跨语言对象,既支持 Java 标准库,也兼容自定义 Java 类、jar 包依赖,是 Python 对接 Java 系统的轻量化方案。

三、py4j 安装方法

py4j 安装仅需通过 pip 执行指令,Python 与 Java 环境均需配置,且 Java 需配置环境变量:

1. Python 端安装

打开命令行执行:

pip install py4j

安装完成后,可通过以下代码验证安装结果:

import py4j
print(py4j.__version__)

执行后输出版本号,即代表 Python 端安装成功。

2. Java 端依赖配置

Java 端无需手动安装,只需引入 py4j 的 jar 包,有两种方式:

  • Maven 项目:在 pom.xml 中添加依赖
<dependency>
    <groupId>net.sf.py4j</groupId>
    <artifactId>py4j</artifactId>
    <version>0.10.9.7</version>
</dependency>
  • 普通 Java 项目:从官网下载 py4j 的 jar 包,添加到项目构建路径即可。

四、基础使用:Python 调用 Java 标准库

这是 py4j 最常用的场景,无需编写自定义 Java 代码,直接调用 Java 内置类,快速体验跨语言调用。

1. Java 端启动网关服务

新建 Java 类,启动 GatewayServer,代码如下:

import py4j.GatewayServer;

public class JavaGateway {
    public static void main(String[] args) {
        // 启动网关服务,默认端口 25333
        GatewayServer gatewayServer = new GatewayServer();
        gatewayServer.start();
        System.out.println("py4j 网关服务启动成功");
    }
}

运行该 Java 程序,控制台输出启动成功,服务进入监听状态。

2. Python 端调用 Java 类

Python 连接网关后,可直接调用 Java 工具类,示例调用 ArrayList、String、Math 类:

from py4j.java_gateway import JavaGateway

# 连接 Java 网关服务
gateway = JavaGateway()

# 1. 调用 Java ArrayList 集合
java_list = gateway.jvm.java.util.ArrayList()
java_list.add("Python")
java_list.add("Java")
java_list.add("py4j")
print("Java ArrayList 内容:", java_list)
print("ArrayList 长度:", java_list.size())

# 2. 调用 Java String 方法
java_str = gateway.jvm.java.lang.String("Hello py4j")
print("字符串转大写:", java_str.toUpperCase())

# 3. 调用 Java Math 工具类
math_result = gateway.jvm.java.lang.Math.sqrt(64)
print("64 的平方根:", math_result)

代码说明

  • JavaGateway():自动连接本地默认端口的 Java 网关,无需手动配置地址;
  • gateway.jvm:核心入口,通过它访问所有 Java 类;
  • 调用方式与 Java 完全一致,支持方法传参、属性获取,降低学习成本。

运行 Python 代码,可正常输出 Java 方法执行结果,实现基础跨语言调用。

五、进阶使用:Python 调用自定义 Java 类

实际开发中,更多是调用自定义 Java 业务类,py4j 完美支持自定义类、对象方法、静态方法调用。

1. 编写自定义 Java 类

新建用户工具类,包含成员方法、静态方法、带参构造方法:

public class UserTool {
    private String username;

    // 无参构造
    public UserTool() {}

    // 带参构造
    public UserTool(String username) {
        this.username = username;
    }

    // 成员方法
    public String sayHello() {
        return "Hello, " + username;
    }

    // 带参成员方法
    public int add(int a, int b) {
        return a + b;
    }

    // 静态方法
    public static String staticMethod() {
        return "这是 Java 静态方法";
    }
}

2. Java 端启动服务(注册自定义类)

无需额外注册,启动网关后,自定义类会自动加载,Python 可直接访问:

import py4j.GatewayServer;

public class CustomJavaServer {
    public static void main(String[] args) {
        GatewayServer server = new GatewayServer();
        server.start();
        System.out.println("自定义 Java 服务启动成功");
    }
}

运行该 Java 程序,确保自定义类已编译生效。

3. Python 调用自定义 Java 类

from py4j.java_gateway import JavaGateway

gateway = JavaGateway()

# 1. 创建自定义 Java 类对象(无参构造)
user_tool = gateway.jvm.UserTool()
# 调用带参构造
user_tool2 = gateway.jvm.UserTool("py4j用户")

# 2. 调用成员方法
hello_msg = user_tool2.sayHello()
print(hello_msg)

# 3. 调用带参方法
add_result = user_tool2.add(10, 20)
print("10 + 20 =", add_result)

# 4. 调用静态方法
static_msg = gateway.jvm.UserTool.staticMethod()
print(static_msg)

代码说明

  • 自定义类无需特殊注解,py4j 自动反射获取类结构;
  • 支持构造方法、成员方法、静态方法全场景调用,与 Java 编码习惯一致;
  • 可传递 int、String、集合等基础类型参数,自动完成类型转换。

运行后可正常获取自定义 Java 类的执行结果,满足业务代码调用需求。

六、高级使用:Java 调用 Python 代码

py4j 支持双向通信,除了 Python 调 Java,还能让 Java 主动调用 Python 函数、对象,实现双向交互。

1. Python 端编写可调用代码

from py4j.java_gateway import JavaGateway

# 启动 Python 网关,允许 Java 调用
gateway = JavaGateway()
python_gateway = gateway.gateway_server

# 定义 Python 函数,供 Java 调用
def python_add(a, b):
    print("Python 函数被调用")
    return a + b

def python_message(msg):
    return "Python 接收:" + msg

# 注册 Python 对象,让 Java 访问
class PythonDemo:
    def test_method(self):
        return "Python 类方法执行成功"

# 注册实例
python_demo = PythonDemo()
gateway.entry_point.python_demo = python_demo
gateway.entry_point.python_add = python_add
gateway.entry_point.python_message = python_message

print("Python 服务已启动,等待 Java 调用...")
# 保持程序运行
while True:
    pass

2. Java 端调用 Python 代码

import py4j.GatewayServer;

public class JavaCallPython {
    public static void main(String[] args) {
        GatewayServer server = new GatewayServer();
        server.start();

        // 获取 Python 入口点,调用 Python 函数
        Object entryPoint = server.getGateway().getEntryPoint();
        try {
            // 调用 Python 加法函数
            int sum = (int) entryPoint.getClass()
                    .getMethod("python_add", int.class, int.class)
                    .invoke(entryPoint, 30, 50);
            System.out.println("Java 调用 Python 加法结果:" + sum);

            // 调用 Python 字符串方法
            String msg = (String) entryPoint.getClass()
                    .getMethod("python_message", String.class)
                    .invoke(entryPoint, "Java 消息");
            System.out.println(msg);

            // 调用 Python 类方法
            Object pythonDemo = entryPoint.getClass()
                    .getField("python_demo")
                    .get(entryPoint);
            String testResult = (String) pythonDemo.getClass()
                    .getMethod("test_method")
                    .invoke(pythonDemo);
            System.out.println(testResult);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

代码说明

  • Python 端通过 entry_point 注册函数、对象,暴露给 Java 调用;
  • Java 端通过反射获取 Python 注册的内容,执行对应逻辑;
  • 双向调用模式,可实现 Python 与 Java 系统的无缝协同,适合老旧 Java 系统升级。

七、实际业务案例:Python 数据分析对接 Java 业务系统

模拟企业真实场景:Java 负责业务数据存储,Python 负责数据分析,通过 py4j 实现数据互通。

1. Java 端:提供数据查询类

import java.util.ArrayList;
import java.util.List;

// 模拟业务数据查询类
public class DataService {
    // 模拟查询用户年龄数据
    public List<Integer> getUserAges() {
        List<Integer> ages = new ArrayList<>();
        ages.add(22);
        ages.add(25);
        ages.add(28);
        ages.add(30);
        ages.add(35);
        return ages;
    }

    // 模拟查询用户姓名
    public List<String> getUserNames() {
        List<String> names = new ArrayList<>();
        names.add("张三");
        names.add("李四");
        names.add("王五");
        names.add("赵六");
        names.add("钱七");
        return names;
    }
}

2. Java 启动服务

import py4j.GatewayServer;

public class DataServer {
    public static void main(String[] args) {
        GatewayServer server = new GatewayServer();
        server.start();
        System.out.println("业务数据服务启动成功");
    }
}

3. Python 端:获取数据并做数据分析

from py4j.java_gateway import JavaGateway

# 连接 Java 服务
gateway = JavaGateway()
data_service = gateway.jvm.DataService()

# 1. 获取 Java 业务数据
ages = data_service.getUserAges()
names = data_service.getUserNames()

# 转换为 Python 列表,方便处理
age_list = [age for age in ages]
name_list = [name for name in names]

print("用户姓名:", name_list)
print("用户年龄:", age_list)

# 2. Python 数据分析:计算年龄平均值、最大值、最小值
avg_age = sum(age_list) / len(age_list)
max_age = max(age_list)
min_age = min(age_list)

print("平均年龄:", round(avg_age, 2))
print("最大年龄:", max_age)
print("最小年龄:", min_age)

# 3. 把分析结果返回给 Java(演示双向交互)
def send_analysis_result(avg, max_age, min_age):
    return f"分析结果:平均年龄{avg},最大{max_age},最小{min_age}"

# 注册方法供 Java 调用
gateway.entry_point.send_result = send_analysis_result
print("分析完成,结果已暴露给 Java 端")

# 保持运行
while True:
    pass

案例价值

该案例贴合企业实际开发场景,Java 负责稳定的业务逻辑、数据管理,Python 发挥数据分析、机器学习优势,通过 py4j 打通两种语言的壁垒,无需重构现有系统,低成本实现功能扩展,既保留 Java 系统的稳定性,又利用 Python 提升数据处理能力。

八、py4j 优缺点总结

优点

  1. 接入成本极低,无需修改原有 Java 代码,无侵入式集成;
  2. 支持 Python 与 Java 双向调用,适用场景广泛;
  3. 兼容所有 Java 类、第三方 jar 包,无需额外适配;
  4. 开源免费,BSD 许可可用于商业项目;
  5. 语法贴近原生语言,学习门槛低,新手易上手。

缺点

  1. 基于 Socket 通信,存在网络开销,不适合超高频调用;
  2. 复杂对象序列化需要手动处理,部分特殊类型支持有限;
  3. 分布式场景下需自行处理服务部署、端口占用问题。

九、相关资源

  • Pypi 地址:https://pypi.org/project/py4j/
  • Github 地址:https://github.com/py4j/py4j
  • 官方文档地址:https://www.py4j.org/

关注我,每天分享一个实用的Python自动化工具。