python打包资源文件(图片等)的方法

一、基本步骤

(一)先使用pyinstaller命令对主程序进行打包

如果没有pyinstaller命令,先进行下载:pip install pyinstaller

打包的两种方式:

pyinstaller -D test.py      # 生成一个文件夹,里面是多文件模式,启动快。
pyinstaller -F test.py       #  仅仅生成一个文件,不暴露其他信息,启动较慢。

Pyinstaller -F setup.py 打包exe

Pyinstaller -F -w setup.py 不带控制台的打包

Pyinstaller -F -i xx.ico setup.py 打包指定exe图标打包

(二)修改spec文件,添加资源

1.修改datas项

datas=[('res/bg.jpg', 'res'), ('exam.db', '.')]

列表里面是元组,左边是你要添加的filename(相对路径即可),右边是拷贝到项目中之后的文件夹名字。
比如:

(‘res/bg.jpg’, ‘res’) 中的 ‘res/bg.jpg’ 表示工程根目录下res文件夹下有bg.jpg图片,拷贝到项目之后的res文件夹。
(‘exam.db’, ‘.’) 中的’exam.db’是工程根目录下的文件,’.'表示根目录,即拷贝到项目中的根目录下。

2.修改pathex项

pathex=['/Users/wenlong/exam_demo']

即添加项目地址

(三)重新编译

注意只需编译spec文件

pyinstaller  test.spec

二、注意事项

(一)修改代码中资源访问路径

# 生成资源文件目录访问路径
def resource_path(relative_path):
    if getattr(sys, 'frozen', False):  # 判断sys中是否存在frozen变量,即是否是打包程序
        base_path = sys._MEIPASS       # sys._MEIPASS在一些编辑器中会报错,不用理会
    else:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)
run_path = resource_path(relative_path)

(二)编译spec文件时不要再加参数(-D,-F等),否则会出错

三、工作原理

(一)基本原理

Pyinstaller 可以将资源文件一起bundle到exe中,当exe在运行时,会生成一个临时文件夹,程序可通过sys._MEIPASS访问临时文件夹中的资源

官方说明:https://pythonhosted.org/PyInstaller/spec-files.html#spec-file-operation

(二)资源路径

程序打包成exe的时,会将一个变量frozen注入到sys中,这里使用判断,检测sys是否有frozen这个变量,如果有,就使用sys._MEIPASS访问临时文件夹路径,如果没有,就使用当前路径,当程序不管是以PyInstaller打包后形式运行,还是本地测试,都能找到正确的资源路径。

这个 sys._MEIPASS 是个特殊的值,是在Pyinstaller打包的时候才会添加的临时变量,通过这个变量我们可以获取到在执行exe时候的临时目录。

四、其它注意事项

WIN和MAC建议这样打包:有多个依赖包必须放在相同文件夹下,

命令:pyinstaller -F 主文件.py -p 副1.py -p 副2.py -w --icon="图标.icns"

注意:

1>如果用ttkthemes主题库,pyinstaller必须添加--hidden-import ttkthemes或者手动添加,然后单独执行pyinstaller xxx.spec;

2>Mac下要向想图标生效,只能Pyinstaller -F -w 主程序.py -i 图标.icns (必须是icns格式目前只知道这样)