如何用PyInstaller将依赖与代码分离生成两个独立exe文件?
实现依赖与代码分离的PyInstaller打包方案
核心思路
把依赖库的打包与业务代码的打包完全拆分:
- 将集中导入第三方库的
imports.py单独打包成imports.exe,所有依赖的二进制文件都整合进这个文件。 - 业务代码
main.py打包成main.exe时,彻底排除第三方依赖,只保留自身逻辑;运行时通过加载imports.exe解压后的依赖目录来调用第三方库。
步骤1:修改imports.py,输出依赖路径
调整imports.py,让它在PyInstaller打包后的运行环境中,把自身解压的依赖目录路径写入临时文件,并输出该临时文件的名称:
import sys import tempfile import os if hasattr(sys, '_MEIPASS'): # 创建临时文件存储依赖目录路径 with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as temp_f: temp_f.write(sys._MEIPASS) # 输出临时文件路径,供main.exe读取 print(temp_f.name)
步骤2:打包imports.py为依赖载体
执行PyInstaller命令,将imports.py打包成包含所有第三方依赖的独立可执行文件:
pyinstaller --name imports --onefile --noconsole imports.py
--noconsole:避免运行时弹出命令行窗口(可根据需求移除)- PyInstaller会自动识别
imports.py中导入的所有库(如pandas、numpy)并打包进imports.exe
步骤3:修改main.py,实现运行时加载依赖
修改main.py,让它启动imports.exe获取依赖目录,将该目录加入Python模块搜索路径后再导入第三方库:
import subprocess import sys import os def load_dependencies(): # 启动imports.exe,获取临时文件路径 proc = subprocess.Popen( ['./imports.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) temp_file_path, _ = proc.communicate() temp_file_path = temp_file_path.strip() # 读取依赖目录路径 with open(temp_file_path, 'r') as f: dep_path = f.read().strip() # 删除临时文件 os.unlink(temp_file_path) # 将依赖目录加入模块搜索路径 sys.path.append(dep_path) # 先加载依赖 load_dependencies() # 现在可以正常导入第三方库 import pandas as pd import numpy as np # 你的业务代码逻辑 if __name__ == '__main__': print("依赖加载成功") print(f"pandas版本:{pd.__version__}")
步骤4:打包main.py为轻量可执行文件
执行PyInstaller命令,打包main.py时排除所有第三方依赖,仅保留自身代码:
pyinstaller --name main --onefile --exclude-module=pandas --exclude-module=numpy main.py
--exclude-module:列出所有需要排除的第三方库(与imports.py中导入的库一致),确保main.exe不包含冗余依赖- 后续仅当
main.py的业务代码变更时,重新执行此命令即可
注意事项
- 确保
main.exe和imports.exe在同一目录下运行,或者在main.py中指定imports.exe的绝对路径 - 若依赖库有更新,只需重新打包
imports.py,无需修改main.exe - 使用
--noconsole打包imports.exe时,需保证临时文件的读写权限正常
内容的提问来源于stack exchange,提问作者Abhishek Sasidharan
相关产品推荐
相关产品推荐

