用ProcessBuilder调用Python脚本最直接,需指定Python解释器绝对路径、脚本绝对路径,读取输入输出流并检查waitFor返回值;Jython仅支持无C扩展的Python 2.7代码,二者适用场景完全不同。

用 Runtime.exec() 或 ProcessBuilder 启动 Python 脚本最直接
Java 本身不解析 Python,所以调用外部脚本本质是启动新进程。用 ProcessBuilder 比 Runtime.exec() 更可控、更安全,尤其处理含空格路径或复杂参数时。
- 必须显式指定 Python 解释器全路径(如
/usr/bin/python3或C:\Python39\python.exe),不能只写python—— Java 进程的PATH环境可能不含它 - Python 脚本路径建议用绝对路径;若用相对路径,实际工作目录是 Java 进程启动时的目录,不是 Java 源码所在位置
- 务必读取
process.getInputStream()和process.getErrorStream(),否则子进程可能因缓冲区满而阻塞(常见“卡死”原因) - 别忽略
process.waitFor()的返回值:非 0 表示 Python 脚本异常退出(比如语法错误、sys.exit(1))
Jython 只能运行兼容 Python 2.7 的纯 Python 代码
Jython 是 Python 解释器的 Java 实现,不是“让 Java 调用任意 Python”,而是把 Python 当作一种 JVM 脚本语言来执行。它和 CPython 完全不兼容。
- 不支持任何 C 扩展模块:
numpy、pandas、cv2、requests(底层用 C 实现的部分)统统不能用 - 语法仅限 Python 2.7 ——
f-string、yield from、类型注解等全报错 - 标准库是精简版,
asyncio、pathlib、dataclasses都没有 - 适合场景极窄:已有遗留 Python 2.7 工具函数,且无第三方依赖,想在 Java 里当工具类用
传参和取结果:别用 System.out.println() 做接口
Python 脚本输出到 stdout 是最常用的数据通道,但容易误读——比如忘记 strip 换行符、混淆编码、忽略 stderr 干扰。
- Python 端显式用
print(json.dumps({...}))输出结构化数据,Java 端用new String(bytes, StandardCharsets.UTF_8)解码,避免平台默认编码差异 - 不要靠打印调试信息混在结果里:Python 脚本里所有
print()都进 stdout,Java 无法区分哪些是日志、哪些是结果 - 如果要传大量数据,别拼接命令行参数(有长度限制且难编码),改用临时文件或 stdin 输入
- 超时必须设:用
process.waitFor(30, TimeUnit.SECONDS),否则 Python 死循环会让 Java 线程永久挂起
Windows 下 python.exe 路径和权限常被忽略
Windows 用户最容易栽在这儿:看似能双击运行的 Python 脚本,在 Java 里调用却报 Cannot run program "python": CreateProcess error=2。
- 不是“没装 Python”,而是 Java 进程找不到
python.exe—— 检查ProcessBuilder.inheritIO()是否误开了,导致看不到真实错误路径 - 从 Windows 应用商店安装的 Python 默认不加 PATH,得手动勾选“Add Python to PATH”或用绝对路径
- 企业环境常见策略限制:即使路径对,也可能因组策略禁止非签名脚本执行(
ExecutionPolicy),此时需在命令前加powershell -ExecutionPolicy Bypass -Command & ... - 杀毒软件有时会拦截 Java 启动的 python 进程,表现为无错误、无输出、等待超时 —— 先关掉实时防护试试