很多时候,我们的代码需要依赖一些资源文件,比如配置文件、默认数据、图片等,如果用PyInstaller进行打包的话,默认是不会将这些文件打包进去的,那么该如何处理这个问题呢?
示例代码
我会通过一段很简单的代码来说明这个问题,下面的代码会通过configparser
读取config.ini
文件,这个例子也来自官方文档:
1 | #!/bin/python3 |
config.ini
的文件内容如下所示:
1 | [DEFAULT] |
现在进行打包:
1 | PyInstaller --onefile load_config.py |
执行时会发生报错:
1 | cd dist |
这是因为在load_config
所在的目录下不存在config.ini
文件,如果我们把config.ini
拷贝一份到目录下就可以正常运行:
1 | ./load_config |
现在回到最开始的问题,如果我们并不需要用户知道这种资源文件的存在,想把config.ini
一起打包进去该怎么做?
spec文件
spec
文件实际上是可执行的Python代码,PyInstaller
通过执行spec
文件的内容来构建应用程序。可以将其理解为写C代码时的makefile
文件,都是用于控制编译构建过程。遇到下面几种情况时需要修改spec文件:
- 需要打包资源文件
- 需要include一些PyInstaller不知道的run-time库
- 为可执行文件添加run-time选项
- 多程序打包
生成spec文件的方式有两种,一种是通过pyi-makespec
命令生成:
1 | pyi-makespec <options> XXX.py |
注意此处的options,如果希望生成一个文件,应该使用--onefile
选项。
在上面进行打包时除了生成build
和dist
两个文件夹外,还有一个load_config.spec
文件,这便是另一种方式啦:
1 | pyinstaller <options> XXX.py |
修改spec文件
先看一下目录结构:
1 | tree |
打开load_config.spec
文件,按照官方文档进行操作,将我们的资源文件添加进去:
1 | a = Analysis(['load_config.py'], |
除此之前我们还需要对代码稍作修改,因为代码执行的时候是释放到/tmp
文件夹的,所以我们需要告知configparser
配置文件config.ini
的绝对路径:
1 | #!/bin/python3 |
现在就可以通过spec
文件进行打包:
1 | pyinstaller load_config.spec |
拷贝到另一台机器上进行测试:
1 | chmod +x load_config |
这样我们就成功的将所需要的资源文件打包进去了。
参考链接
1、https://docs.python.org/zh-cn/3/library/configparser.html
2、https://pythonhosted.org/PyInstaller/spec-files.html#adding-data-files