Python之点到为止: 优美的打包你的代码(二)优化

2020年04月21日 510点热度 0人点赞 0条评论

会打包我们就要开始优化了, 无外乎是启动速度和文件大小.

优化方向

就目前来说方向就三个: 启动速度、运行效率、文件大小.

启动速度

这里这个启动速度, 是指从双击再执行第一句Python语句的速度.

import time

def count_time(func):
    def int_time(*args, **kwargs):
        start_time = time.time()
        func()
        over_time = time.time()
        return over_time - start_time
    return int_time

@count_time
def run():
    res = []
    for i in range(10000000):
        res.append(i)
    del res

if __name__ == "__main__":
    print(time.time())
    t = 10
    all = 0
    for i in range(t):
        all += run()
    print(all/t)

经过测试, 在一些简单的环境下启动速度几乎相同, PyInstaller打包单文件(-F)稍微有点停顿感. 本来还想具体测一下启动时间的差别, 但是后续想了一下, 如果正常双击察觉不到卡顿感觉应该就可以了, 所以最后目测的哈哈?. cx-Freeze因为没有单文件打包, 正常打包启动速度与PyInstaller (-D) 速度几乎无异.

PS: 如果使用PyInstaller加密字节码的话肯定是在启动速度上有妥协.

运行效率

运行效率在使用打包运行环境这类模块几乎没差别, 因为这类你可以粗略的理解先将Python环境解压然后调用Python xxx.pyc . 所以除了解压环境和代码会浪费时间外其余和正常运行理论上无异. Nuitka那还用说么, 已经变成C了. 官网号称比CPython快两倍以上, 因为手里有几个小程序已经使用这个进行编译了. 所以Nuitka就没有参加测试, 感觉不是特别公平哈哈哈.

文件大小

PyInstaller

这个文件大小有点迷, 之前测试代码直接在Conda环境里新建了一个Python3.7, 就上面的代码打包6.15 MB. 非单文件是13.1 MB. 然而文件挺大为了严谨单独安装了一下3.7,打包结果单文件6.18MB, 非单文件是13.2 MB. 发挥挺稳定.

cx-Freeze

这个模块在Conda和正常Python中打包有差异. 打包后的文件树也与PyInstaller有很大差别. Conda创建的环境打包文件17.4 MB, 正常安装的Python环境打包13.2 MB.

大概看了一下, 多出的文件python37.dll, 在lib文件夹中发现重复的这个dll文件. 还有一些没什么卵用的vc运行库dll. 可能是复制文件某些逻辑问题? 没有深去探究.

Nuitka

这个打包有些特殊, 为了他新建了个干净的虚拟机安装了相关程序. 单独用来打包, 但是Python版本是3.8, Nuitka 0.6.7版本已经对3.8进行了支持. 也是上述代码打包文件大小20.2 MB. 嘶~~~ 打包目录文件有点类似PyInstaller

优化

启动速度、运行效率、文件大小. 这三个我们能优化的就是运行效率和文件大小. 而启动速度目前有区别的就是PyInstaller单文件打包, 尽量不用就行了. 运行效率就靠你的"手法"了, 多优化自己的代码.

文件大小还是有很大优化空间的, 先说最大的Nuitka打包竟然20M.

原本有张截图的, 图床挂了就算了. 截图里展示了打包后都有什么文件而已.

默认自带的所有pyd文件全部打包, 然而回头看一下代码. 根本没有用到这些库, 怎么办? 直接删掉!!!!! 删这些文件是有讲究的, 如果你调用的库比较多, 那么就要考虑是否调用了.

PyInstallercx-FreezeNuitka
Default13.213.2-
Conda13.117.420.2
优化后5.734.6611.0
UPX3.422.463.59
RAR3.042.293.80
7zip2.711.963.50
单位: 兆(M)

这个表格UPX是用的是3.9.6版本最高压缩(-9), RAR和7zip都是Windows上默认最高压缩比, 字典以及其他参数为默认. 其中RAR为打包自解压默认执行程序.

这就是我为什么喜欢cx-Freeze的原因, 优化后文件最小. Nuitka文件大但是效率最高.

本文中示例代码以及打包前后对比的文件夹均已分享在Github中, https://github.com/Virace/python-jgah/tree/master/Main/2162 为了方便下载将Before和After两个文件夹内部打包.

PyInstallercx-FreezeNuitka
执行第一次1.00480.88580.8698
执行第二次0.87740.87810.8011
执行第三次0.89680.87540.8043
执行第四次0.88120.90450.8117
优化后UPX执行输出时间(单位:秒)

这个代码最后输出的就是循环100W次将所有数添加到列表中, 这个操作循环10次取平均用时. 因为只是循环添加吃内存, 缺少计算环节, 所以表这个仅供参考. 整体差距还是不大的, 但还是能看出在这个代码上Nuitka还是有性能上的提升的.

总结

用Python打包怎么包最后都不小, 虽说最后优化最小的已经可以2M左右了, 但是对一个这么简单功能的程序都需要2M感觉有点难受. 另外如果你对运行效率有要求别想了Nuitka没跑了, 去看文档优化代码吧.

那么我就点到为止了
Just give a hint.

相关链接:
Pyinstaller文档: https://pyinstaller.readthedocs.io/en/stable/usage.html
ex_Freeze文档: https://cx-freeze.readthedocs.io/en/latest/overview.html
Nuitka文档: https://www.nuitka.net/doc/user-manual.html
本期文件: https://github.com/Virace/python-jgah/tree/master/Main/2162

文章评论