PyInstaller打包含face_recognition的人脸识别代码:py版正常,exe无法运行
人脸识别程序PyInstaller打包后无法启动的排查与解决方案
第一步:先定位真实崩溃原因
在修改任何配置之前,必须先拿到程序的实际报错信息,所有不看报错就盲改配置的操作都是无效的:
- 打开Windows命令提示符(CMD),把打包生成的exe文件直接拖拽到CMD窗口内,按回车键启动
- 完整记录CMD窗口中输出的所有错误堆栈、文件缺失提示
*注意:直接双击exe的启动方式不可取,很多崩溃场景下控制台窗口会在报错后立刻关闭,根本看不到具体错误信息。
核心常见根因与对应修正
1. 模型文件打包路径与库的加载逻辑不匹配
你之前的.spec配置存在路径规则的典型错误:
- PyInstaller中
binaries和datas的元组格式为(源文件相对/绝对路径, 打包后存放的目标目录),你之前给模型文件写的目标路径./face_recognition_models/models是无效的,开头的./需要去掉,PyInstaller会自动将其识别为打包根目录下的对应路径 - 最关键的逻辑错位:
face_recognition库加载内置模型时,会固定查找自身安装包目录下的face_recognition_models/models路径,并不会读取程序同级目录下的自定义路径——这也是你反复把模型文件打包进去,程序依然启动崩溃的核心原因。 - 反复把模型文件在
binaries和datas配置中来回切换,本质是没有对齐库本身的文件查找规则。
正确的模型打包配置不需要手动逐一列举.dat文件,直接用PyInstaller内置的工具收集即可:
# 在.spec文件开头引入工具,自动收集face_recognition_models包的所有数据文件 from PyInstaller.utils.hooks import collect_data_files face_model_datas = collect_data_files('face_recognition_models')
把获取到的face_model_datas直接传入datas参数,PyInstaller会按照库的原目录结构把所有模型文件打包进去,完全匹配库的加载路径。
2. scipy相关配置前后冲突
你当前的配置存在三处明显的逻辑矛盾:
- 手动列举了几十条scipy相关的hiddenimports,同时自定义的
hook-scipy.py里,先把hiddenimports设置为全量收集scipy子模块,后面又直接覆盖为仅3个scipy._lib的子模块,前后逻辑完全冲突 - 手动添加
a.datas += Tree('./scipy-extra-dll', prefix=None),会把本地存放的scipy dll文件直接覆盖到打包目录,版本不匹配时会直接导致程序启动时dll加载失败 - 自定义的
hook-scipy.py完全冗余,现在PyInstaller自带的官方scipy hook已经覆盖了Windows环境下所有scipy dll、子模块的收集逻辑,自行重写反而会破坏原有正确的收集流程。
对应修正操作:
- 删除本地自定义的
hook-scipy.py文件,保留hookspath=[]的配置,让PyInstaller调用自带的官方scipy hook - 删除手动列举的所有scipy相关hiddenimports条目,PyInstaller的scipy hook会自动收集所有运行需要的子模块,手动列举反而容易漏写、错写
- 删除
a.datas += Tree('./scipy-extra-dll', prefix=None)这行配置,不要手动塞入版本不匹配的scipy dll - hiddenimports列表只保留你自身代码中实际import、PyInstaller自动扫描没识别到的第三方库即可。
3. 打包模式与压缩配置的常见坑
你当前的.spec配置采用单文件(onefile)打包模式,这种模式下:
- dlib、scipy这类带大量原生dll的库,在程序自动解压的临时目录中运行时,经常会出现dll加载顺序错误、权限不足导致的启动失败
- 调试过程中根本看不到临时解压目录的文件结构,没法快速定位缺失的文件
对应修正操作:
- 调整.spec的打包逻辑,先改成文件夹(onedir)模式调试:
# 修改EXE块配置,把原来直接传入EXE的binaries、datas、zipfiles移到单独的COLLECT块 exe = EXE(pyz, a.scripts, [], # 空列表占位,所有二进制和数据文件放到下方COLLECT块 name='你的程序名', debug=True, # 先开启debug模式,输出更详细的启动日志 strip=False, upx=False, # 先关闭UPX压缩 runtime_tmpdir=None, console=True ) # 新增COLLECT块,把所有非脚本文件放到程序文件夹内 coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=False, name='你的程序名')
- 调试阶段一定要关闭UPX压缩:UPX压缩很容易把dlib、scipy的原生dll压坏,导致启动时直接报dll加载失败、入口点缺失
- 先运行文件夹模式下的exe,确认能正常启动、加载人脸识别模型、完成核心功能后,再根据需求调整回单文件模式、关闭控制台窗口。
内容的提问来源于stack exchange,提问作者Siddhesh Khadapkar
相关产品推荐
相关产品推荐

