PyInstaller打包Kivy+OpenCV视频灰度工具遇递归深度超限错误求助
问题:PyInstaller打包Kivy+OpenCV视频灰度转换应用出现递归深度超限错误
问题背景
- 开发基于Kivy和OpenCV的桌面应用,实现视频转灰度功能
- 开发环境中运行正常,但使用以下PyInstaller命令打包后报错:
Failed to execute script 'main' due to unhandled exception: maximum recursion depth exceeded
- 打包命令:
pyinstaller --name VideoCartoonizer --windowed --onefile main.py
错误日志
File "logging\__init__.py", line 1084, in emit AttributeError: 'NoneType' object has no attribute 'write' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "logging\__init__.py", line 1084, in emit AttributeError: 'NoneType' object has no attribute 'write' ...(重复错误栈省略) RecursionError: maximum recursion depth exceeded
问题根源分析
- 视频处理逻辑严重错误:原代码中循环用
concatenate_videoclips拼接新生成的VideoClip,会创建嵌套层级极深的剪辑对象,最终触发递归深度超限。同时VideoClip的lambda参数完全不符合MoviePy的帧生成规则——该函数应接收时间t并返回对应帧,而非直接弹出队列元素。 - 窗口模式日志异常:
--windowed模式下Kivy日志无法输出到控制台,引发AttributeError,后续错误处理的连锁反应触发递归错误。
修复方案
1. 重构核心视频处理逻辑
替换原convert_video方法,使用MoviePy标准的帧处理方式:
def convert_video(self, *args): # 获取输入文件路径 input_file = self.input_file.text if not input_file: return # 定义帧处理函数:MoviePy帧为RGB格式,需适配OpenCV def process_frame(frame): # 按比例调整帧大小 aspect_ratio = frame.shape[1] / frame.shape[0] target_width = 640 target_height = int(target_width / aspect_ratio) resized_frame = cv2.resize(frame, (target_width, target_height)) # RGB转BGR(OpenCV格式)→ 转灰度 → 转回RGB(适配MoviePy) gray_bgr = cv2.cvtColor(resized_frame, cv2.COLOR_RGB2GRAY) gray_rgb = cv2.cvtColor(gray_bgr, cv2.COLOR_GRAY2RGB) return gray_rgb # 生成输出路径并处理视频 output_file = input_file.replace(".mp4", "_cartoon.mp4") self.output_file.text = output_file with VideoFileClip(input_file) as input_video: # 使用fl_image批量处理所有帧,MoviePy标准用法 output_video = input_video.fl_image(process_frame) # 写入输出视频 output_video.write_videofile(output_file, codec='mpeg4')
2. 解决窗口模式日志问题
在代码开头添加日志配置,避免无控制台时的输出错误:
import logging from logging.handlers import NullHandler # 配置空日志处理器,防止窗口模式下日志报错 logging.basicConfig(handlers=[NullHandler()], level=logging.INFO)
3. 优化PyInstaller打包命令
添加Kivy和MoviePy的必要依赖声明,确保打包完整:
pyinstaller --name VideoCartoonizer --windowed --onefile --hidden-import=kivy.deps.sdl2 --hidden-import=kivy.deps.glew --hidden-import=moviepy.video.fx.all --hidden-import=moviepy.audio.fx.all main.py
关键注意事项
- MoviePy的
fl_image是批量处理视频帧的标准方式,无需手动循环拼接剪辑 - MoviePy帧格式为RGB,OpenCV默认是BGR,转换时必须做通道适配
- 灰度帧需转回3通道RGB,否则MoviePy写入视频时会格式报错
- 打包时必须显式声明Kivy的底层依赖和MoviePy的特效模块,避免缺失依赖
内容的提问来源于stack exchange,提问作者Thug Medium
相关产品推荐
相关产品推荐

