目录

PyInstaller打包单EXE时封装额外的资源文件

众所周知 PyInstaller 可以将 Python 脚本打包成单一的可执行文件,那么如果程序需要访问自带的外部资源时该怎么办呢?

封装资源文件的必要性

  1. 制作绿色便携的单EXE可执行文件
  2. 有些文件不希望让最终用户轻易看到
  3. 干净

目录

建立配置文件

键入下列指令建立spec配置文件,参数与直接使用PyInstaller时使用的参数相同,程序会自动帮你添加到配置文件中。

pyi-makespec -F -w –icon=<YourICON>.ico <YourPyScript>

使用类似pyinstaller -F XXX.spec编译二进制程序时添加的参数可能没有效果。

编辑配置文件

依据实际情况添加配置文件的引用。

datas

此法适用于添加单个或几个文件

找到Analysis()datas=[],每个文件一个tuple(元组)格式如下:

a = Analysis(
            ...
            datas=[('文件在当前系统中的位置','文件在可执行文件运行时相对于可执行文件的位置')],
            ...
            )

使用通配符可以同时添加所有匹配的文件

a = Analysis(
     ...
     datas= [ ('/mygame/sfx/*.mp3', 'sfx' ) ],
     ...
     )

更多高级用法请阅读PyInstaller文档(英文):Adding Data Files

Tree

此法适用于添加一整个目录的文件

首先,在spec文件中添加如下内容:

extra_tree = Tree('./myimages', prefix = 'myimages')

然后在 a.scripts 等 a. 开头文件所在的部分后添加 extra_tree

表示还没有深入理解Tree,先复制粘贴了其他神触的步骤。

更多高级用法请阅读PyInstaller文档(英文):The Tree Class

修改代码引用

在脚本开头添加下列代码:

import sys, os
if getattr(sys, 'frozen', False):  # 运行于 |PyInstaller| 二进制环境
    basedir = sys._MEIPASS
else:  # 运行于一般Python 环境
    basedir = os.path.dirname(__file__)

找到所有涉及相对路径的文件操作,在路径前添加basedir+。示例:

    with open(os.path.normpath(basedir + '\\ui.kv'), 'r', encoding='UTF-8') as f1:
        kv_str = f1.read()

其中 os.path.normpath() 用于标准化路径。详细信息请自行查阅 Python 文档

经此法修改的脚本可同时在单exe和使用解释器运行时使用相对路径读取打包的资源文件。

编译

接下来的步骤就比较轻松了,直接使用PyInstaller编译然后到./dict文件夹中找到你刚编译出来的可执行文件即可。

pyinstaller <YourPyScript>.spec

参考资料

额外说明

[CRITICAL] [Window      ] Unable to find any valuable Window provider.

如果要打包的程序使用了Kivy框架,则spec文件需做点修改,否则打包出的EXE由于依赖缺失无法正常加载窗口。

# spec文件头部添加
from kivy.deps import sdl2, glew

#修改EXE(),添加需在**第一个关键词参数的前面**进行。
exe = EXE(
          ...
          *[Tree(p) for p in(sdl2.dep_bins + glew.dep_bins)],
          ...
          )