Pyinstaller使用Merge方法打包多程序出现python38.dll丢失问题
问题根源
使用MERGE方法后,Python运行时dll等共享依赖只会被打包到第一个传入MERGE的程序(ONE.exe)的资源中,TWO.exe的对应共享依赖会被剔除,默认需要从ONE.exe的运行时目录加载对应文件,你的现有配置和调用逻辑没有适配这一规则,所以触发dll缺失报错。
解决方案
1. 修正SPEC文件配置
你现有SPEC文件中da_exe(TWO.exe的生成配置)和COLLECT部分传入了重复的共享资源,需要做如下修改:
- 删除
da_exe配置中的da.binaries、da.zipfiles、da.datas参数,MERGE后TWO.exe不需要重复打包这些共享资源,修正后的da_exe配置如下:
da_exe = EXE(da_pyz, da.scripts, [], name='TWO', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=True, disable_windowed_traceback=False, target_arch=None, codesign_identity=None, entitlements_file=None )
- 简化COLLECT配置,不需要重复传入da的资源,避免冗余:
coll = COLLECT(la_exe, la.binaries, la.zipfiles, la.datas, da_exe, strip=False, upx=True, upx_exclude=[], name='Combined_Foo', )
2. 适配运行逻辑
如果你使用文件夹发布模式(推荐)
直接使用COLLECT生成的Combined_Foo文件夹发布,该目录下已经包含共享的python38.dll和所有依赖,ONE.exe调用同目录下的TWO.exe时不会出现dll缺失问题,且不需要每次启动解压,启动耗时会大幅缩短,完全符合你的优化需求。
如果你坚持使用单文件发布模式
- 将生成的TWO.exe作为数据文件添加到ONE的Analysis的datas列表中:
('路径/到/TWO.exe', '.') - 在ONE.py的代码中调用TWO.exe前,先获取ONE运行时的临时解压目录(PyInstaller内置环境变量
MEIPASS对应路径),将TWO.exe的路径指定为该目录下的文件,同时将该目录加入系统PATH环境变量后再启动TWO进程,示例代码如下:
import os import subprocess import sys # 获取ONE的解压目录 base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__))) two_path = os.path.join(base_path, 'TWO.exe') # 将解压目录加入PATH os.environ['PATH'] = base_path + os.pathsep + os.environ.get('PATH', '') # 调用TWO subprocess.Popen(two_path)
3. 可选验证步骤
打包完成后先打开Combined_Foo目录,检查是否存在python38.dll,直接手动双击运行目录下的TWO.exe,如果还是报错,可以将python38.dll手动加入da的binaries列表临时适配:binaries=[('路径/到/你的/python38.dll', '.')],正常情况下修正SPEC后不需要这个操作。
内容的提问来源于stack exchange,提问作者rohith santosh
相关产品推荐
相关产品推荐

