pyinstaller打包Python程序时,文件过大等问题的解决方案


众所周知,pyinstaller常规的打包方法为

pyinstaller -w -F xxx.py

其中,-w表示在执行文件时不打开命令行;-F表示生成单个文件(file)。不加这两个参数,会默认为打开命令行,并把程序生成在一个文件夹中。

通过pyinstaller -F打包程序有以下几个问题

  1. 生成文件的图标是固定的,打开文件后窗口的图标也是固定的,而且这两个图标并不相同
  2. 生成文件过大,几百兆起步
  3. 生成单文件,则启动速度很慢,几秒钟起步
  4. 如果使用窗口程序的同时还用了多进程,会使得每个进程都创建一个窗口

接下来,对这四个问题逐一解决。

图标问题

pyinstaller提供了-i参数,可以用自己的图标来替换

pyinstaller -F -w -i ./yyy.ico xxx.py

但这个图标仅仅表示生成可执行文件的图标,而打开软件后,窗口左上角的图标并非pyinstaller规定的,而是Python所调用的窗口模块所决定的。以tkinter为例,可通过调用iconbitmap来规定

win.iconbitmap("yyy.ico")

在使用pyinstaller打包之后,尽管将图标文件放在了可执行文件所在的文件夹里,但并没有什么卵用。换言之,打包之后的程序可能找不到ico文件,所以一个解决方案是,将ico文件转换为其他可以找到的文件。

具体方法是,将ico文件编码为字符

import base64
# yyy.ico为准备打开的图标文件
# tmp.txt为另存为的文本文件
with open("yyy.ico","rb") as i:
    b64str = base64.b64encode(i.read())
    with open("ico.txt","ab+") as f:
        f.write(b64str)

然后在Python的窗口程序中,将ico.txt打开,复制其中的内容,将其作为字符串赋给一个变量,设这个变量为ICON_TXT,然后将

import tkinter as tk
from icon import Icon
import base64
# 打开文本文件,获取数据
with open("ico.txt","rb") as tmp:
    ICON_TXT = tmp.read()
# 新建图标文件

root = tk.Frame()
with open('tmp.ico','wb') as tmp:
   tmp.write(base64.b64decode(ICON_TXT))
root.iconbitmap('tmp.ico')      #调用
os.remove('tmp.ico')            #删除

生成文件过大的问题

原因很简单,是因为打包的过程中将大量不需要的模块一同打进去了。网上流传的解决方案几乎都是用conda创建一个Python环境,从而只下载自己想要的包。

但网传的大部分见解都语焉不详,就算用conda新建一个python环境,同样也会在创建过程中载入大量不需要的模块,所以问题的关键是创建一个纯净的Python环境。

conda当然是可以做到的,其命令格式为

conda create --name envname --file env.txt

其中,envname为想要创建的虚拟环境的名字;--file说明conda将遵照一个文件来创建Python环境,后面跟着的env.txt就是这个文件,其内容为

@EXPLICIT
https://repo.anaconda.com/pkgs/main/win-64/python-3.9.7-h6244533_1.tar.bz2
https://repo.anaconda.com/pkgs/main/win-64/pip-22.1.2-py39haa95532_0.tar.bz2

这两个网址分别是python3.9和其对应的pip的网址,如果想安装其他模块或者不同的版本,当然也可以修改。

如果将要打包的项目需要用到其他模块,需要在conda环境中,用pip来进行安装。

> conda activate envname
> pip install numpy
> pip install pyinstaller

而且,务必用pip重新安装一次pyinstaller,这样保证在这个纯净的python环境中调用的也是一个纯净的pyinstaller。

对比之下,使用普通conda环境打包的独立可执行文件233MB,使用纯净conda环境输出独立可执行文件22MB,可以说效果相当明显了。

打开速度过慢问题

所谓单文件版,可以简单地理解为把程序做了一个压缩,然后在点击这个可执行文件后,将压缩好的这些文件解压出来,解压之后再正常使用。

所以打开速度过慢的主要原因就是文件太大了,一个几百兆的文件和一个几十兆的文件,解压速度不可同日而语。在这个意义上来讲,解决了生成文件过大的问题,也就相当于解决了打开速度慢的问题。

那么,有没有更快的办法呢?

答案当然是有滴,只要找到一种比较快的解压方法就可以了,而封包工具还是比较多的,比如enigama virtualbox

首先,用pyinstaller -D的方法,将python代码以文件夹的形式打包。

pyinstaller -w -D test.py

然后,打开enigma virtualbox,设置好输入和输出的可执行文件,把pyinstaller生成的文件夹递归加入,然后点击打包,就可以生成单文件了。

在这里插入图片描述

最后尽管输出的文件比pyinstaller打包的单文件要稍大一些,但启动时的速度快了很多。

多线程问题

这个问题反而很好解决,只需在程序入口添加一条语句

import multiprocessing
if __name__ == '__main__':
    multiprocessing.freeze_support()

关于freeze_support的用法,在Python的官方文档上有写,是专门用于冻结multiprocessing程序生成Windows可执行文件的。

而且标准库文档还特意强调,在 py2exe, PyInstaller 和 cx_Freeze 上测试通过。

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微小冷

请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值