Flask应用通过subprocess调用recasepunc.py时返回Error in recasepunc: None错误的解决求助
看起来你遇到了个挺挠人的问题——明明在终端里用echo管道调用recasepunc完全正常,放到Flask里用subprocess调用就只返回Error in recasepunc: None,连个有用的错误信息都没有。我来帮你拆解一下可能的原因,以及怎么拿到真正的错误信息来解决问题。
首先,搞清楚为什么stderr是None
你现在用的subprocess.check_output()在子进程以非0状态退出时,会抛出CalledProcessError,但如果用了shell=True,有时候没办法正确捕获子进程的stderr输出,就会显示None。咱们先换个更可靠的调用方式,把所有输出都抓下来,这样就能看到真正的错误了。
第一步:修改subprocess调用代码,捕获完整输出
把你调用recasepunc的代码块换成下面这样,用subprocess.run()代替check_output(),同时避开shell=True的坑:
import sys import os # 先获取脚本和checkpoint的绝对路径,避免工作目录不一致的问题 current_dir = os.path.dirname(os.path.abspath(__file__)) recasepunc_script = os.path.join(current_dir, "recasepunc", "recasepunc.py") checkpoint_path = os.path.join(current_dir, "recasepunc", "checkpoint") try: # 不用shell=True,把命令拆成列表形式更安全可靠 proc_result = subprocess.run( [sys.executable, recasepunc_script, "predict", checkpoint_path], text=True, input=recognized_text, capture_output=True, check=True ) processed_text = proc_result.stdout.strip() # 去掉多余的换行符 except subprocess.CalledProcessError as e: # 把stdout和stderr都返回,就能看到真正的错误内容了 processed_text = f"Error in recasepunc: stdout={e.stdout}, stderr={e.stderr}" except Exception as e: processed_text = f"Unexpected error when calling recasepunc: {str(e)}"
为什么要这么改?
- 用
sys.executable代替直接写python:避免Flask运行的虚拟环境和系统默认Python版本不一致,导致找不到recasepunc需要的依赖(比如torch、transformers)。 - 用绝对路径指定脚本和checkpoint:Flask的工作目录可能和你手动测试时的终端目录不一样,绝对路径能避免“找不到文件”的问题。
- 不用
shell=True:既安全(避免命令注入风险),又能保证子进程正确读取stdin的输入文本。 capture_output=True:不管子进程把错误信息输出到哪里,都会被捕获,再也不会出现None的情况。
第二步:修正音频处理的小bug
我还注意到你处理音频的代码里有个小问题,会导致通道设置无效:
wavv = song.set_channels(CHANNELS) wavv = song.set_frame_rate(FRAME_RATE)
第二行你又用了原始的song对象,而不是修改后的wavv,前面的通道设置等于白做了!应该改成:
wavv = song.set_channels(CHANNELS) wavv = wavv.set_frame_rate(FRAME_RATE)
这个bug虽然和当前的recasepunc错误无关,但修正后能保证Vosk识别的音频格式是正确的,避免后续其他问题。
第三步:增加输入文本校验
在调用recasepunc之前,先判断一下recognized_text是不是空字符串——如果Vosk识别失败,传空文本给recasepunc也可能导致报错,加个简单的判断:
recognized_text = json.loads(result)["text"] if not recognized_text: return jsonify({ "recognized_text": recognized_text, "processed_text": "Error: No text was recognized from the audio file" })
接下来怎么做?
按照上面的修改重新运行Flask应用,再测试一次,你会在processed_text里看到真正的错误信息了——比如:
- 如果是路径问题,会看到
FileNotFoundError: [Errno 2] No such file or directory - 如果是依赖问题,会看到
ModuleNotFoundError: No module named 'xxx' - 如果是输入文本的问题,会看到recasepunc本身的错误提示
拿到真正的错误后,就能针对性解决了!比如如果是依赖问题,就把recasepunc需要的包安装到Flask的虚拟环境里;如果是路径问题,就调整脚本或checkpoint的路径。
备注:内容来源于stack exchange,提问作者Xenia

