问题:
在一个虚拟环境(venv)中使用 pyinstaller 打包文件时会尝试分析代码,并确定它所依赖的所有库。但这可能会误报或过度包含库,导致打包完后的文件过大。
原因分析:
1、动态导入:如果代码中使用了动态导入(例如,通过 importlib),分析器可能会误判依赖关系。
2、隐藏的依赖关系:有些库可能有隐藏的依赖关系,这些依赖关系在运行时才被导入。为了确保生成的可执行文件在所有情况下都能正常工作,打包工具可能会过度包含库。
3、虚拟环境的内容:即使没有在项目中直接使用某些库,但如果这些库存在虚拟环境中,打包时可能会一并带上。
4、默认的钩子:pyinstaller 使用 “hooks”(钩子)来处理特定的库。这些钩子可能会导致额外的库被包含进来。
解决方案:
要减少不必要的库的包含,可以尝试以下方法
1、清洁的虚拟环境:在一个新的、只包含您项目真正需要的库的虚拟环境中打包您的应用程序。
2、自定义钩子:为 pyinstaller 创建自定义的钩子,以更精确地控制哪些库被包含或排除。
3、手动排除库:使用 pyinstaller 的 exclude 选项来手动排除不需要的库。
4、使用.spec文件:使用 .spec 文件允许您更细粒度地控制打包过程,包括添加和排除特定的依赖关系。
♥使用.spec文件(重点介绍):
使用 .spec 文件可以为 pyinstaller 提供更详细的指示,告诉它如何打包您的应用。这个文件定义了很多配置参数,允许您更精确地控制打包过程,如添加或排除依赖。
首先,如果您还没有一个 .spec 文件,可以通过运行 pyinstaller 来自动生成一个:
pyinstaller XXX.py
这会生成一个 XXX .spec 文件。
打开 XXX .spec 文件,会有配置项:
-
Analysis(分析):
Analysis 在 .spec 文件中的参数 excludes ,可以用来排除库:
a = Analysis(['XXX.py'],
pathex=['/path/to/your/script'],
binaries=[],
datas=[],
excludes=['unnecessary_library1', 'unnecessary_library2'], # 这里列出你想排除的库
...
)
完成上述修改后,在终端使用以下命令(使用 .spec 文件)来打包应用程序:
pyinstaller XXX.spec
即可完成程序的精简打包。