SpringBoot调用Python脚本异常排查:手动正常但Java调用卡住
问题:SpringBoot调用Python脚本卡在视频写入步骤,手动执行正常
背景信息
我有一个名为movie.py的Python脚本,存放路径为resources/movie-python,脚本导入内容如下:
import os from moviepy.video.io.VideoFileClip import VideoFileClip from moviepy.video.VideoClip import TextClip from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip import subprocess import moviepy.config as conf from moviepy.audio.io.AudioFileClip import AudioFileClip import pyttsx3
手动在脚本目录执行python movie.py时运行完全正常,但通过SpringBoot的Java代码调用时,脚本会卡在video_with_text.write_videofile(temp_file, codec='libx264', audio_codec='aac')这一行,无法继续执行。
Java调用代码
public void callPythonFile() { try { // Directory where the Python script is located final File scriptDirectory = new File("src/main/resources/movie-python"); // Command to run the Python script final String command = "python movie.py"; // Start the process with the script directory as the working directory ProcessBuilder processBuilder = new ProcessBuilder(command.split(" ")); processBuilder.directory(scriptDirectory); Process process = processBuilder.start(); // Read output from the process InputStream inputStream = process.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } // Wait for the process to finish int exitCode = process.waitFor(); if (exitCode != 0) { throw new RuntimeException("Python script exited with non-zero code: " + exitCode); } System.out.println("Python script exited with code: " + exitCode); } catch (IOException | InterruptedException e) { throw new RuntimeException("Error executing Python script: " + e.getMessage(), e); } }
核心原因分析
1. 标准错误流未读取导致阻塞
Java代码仅读取了子进程的标准输出流(InputStream),但忽略了标准错误流(ErrorStream)。MoviePy执行视频写入时会输出大量日志到标准错误,当错误流的缓冲区被填满后,子进程会被强制阻塞,无法继续执行后续逻辑。
2. Python环境不匹配
手动执行时使用的是当前终端关联的Python环境,而Java启动子进程时默认使用系统全局的Python环境,两者的依赖包版本、路径配置可能存在差异。比如MoviePy依赖的ffmpeg路径未正确配置,导致无法调用编码器完成视频写入。
3. 文件权限与路径问题
虽然设置了脚本目录为工作目录,但SpringBoot运行进程的用户权限可能和手动执行的用户不同,导致临时文件temp_file无法创建或写入。另外,如果temp_file使用相对路径,在Java进程的上下文里可能解析到错误的位置,引发写入阻塞。
4. Pyttsx3的无终端兼容性问题
脚本中导入的pyttsx3是一个语音合成库,它依赖交互式终端环境。在Java调用的无终端子进程中,该库可能初始化失败或陷入等待输入的状态,间接导致整个脚本卡住。
解决建议
- 同时处理标准错误流:新增线程读取
process.getErrorStream(),避免缓冲区溢出阻塞进程。 - 指定Python解释器完整路径:将命令中的
python替换为手动执行时使用的Python完整路径(比如/usr/bin/python3.8或C:\Python39\python.exe),确保环境一致。 - 使用绝对路径处理临时文件:修改Python脚本中
temp_file的路径为绝对路径,同时检查SpringBoot运行用户对该路径是否有读写权限。 - 调整Pyttsx3配置:初始化
pyttsx3时指定无头模式,或者在Java调用时设置环境变量PYTHONUNBUFFERED=1禁用输出缓冲,避免交互等待。
内容的提问来源于stack exchange,提问作者Tanabata Cinco
相关产品推荐
相关产品推荐

