美文网首页
周日趣事:看看python脚本怎么打包成可执行文件(应用)

周日趣事:看看python脚本怎么打包成可执行文件(应用)

作者: 赖皮姑娘爱吃蛋糕 | 来源:发表于2023-04-08 17:50 被阅读0次

    背景

    同事A需要在一台只能访问局域网的mac mini上运行一个python脚本,脚本依赖了一些模块,有numpy这种三方模块,也有自己开发的本地模块,而mac mini上除了python,什么都没有安装。同事B接到求助后三下五除二生成了一个可执行文件,堪称满分答案。但对于具体细节,同事B表示很复杂说不清,于是就有了姑娘的周日趣事。

    工具

    浅百度一下,迅速定位到工具为PyInstaller, 查到官网上有以下描述,确认就是你没错!

    PyInstaller bundles a Python application and all its dependencies into a single package. The user can run the packaged app without installing a Python interpreter or any modules.

    从首页的描述来看,使用简直不能再简单:
    安装工具:

    pip install -U pyinstaller

    使用工具:

    pyinstaller your_program.py

    真的这么简单吗?

    如果同我一样顺手用了import numpy做demo的话,就不是了!
    我的脚本tryPyinstaller.py:

    import numpy as np
    print("6 / 3 = " + str(np.divide(6,3)))

    使用工具:

    pyinstaller --onefile tryPyinstaller.py

    运行生成的应用:

    (base) leixiaoyues-MacBook-Pro:~ leixiaoyue$ /Users/leixiaoyue/Code/YuePythonScript/tryPyinstaller/dist/tryPyinstaller ; exit;
    INTEL MKL ERROR: dlopen(/private/var/folders/fq/qx5csyvd54x6p60p38qvqfpm0000gn/T/_MEI8YGfHc/libmkl_intel_thread.1.dylib, 0x0009): Library not loaded: '@rpath/libiomp5.dylib'
    Referenced from: '/private/var/folders/fq/qx5csyvd54x6p60p38qvqfpm0000gn/T/_MEI8YGfHc/libmkl_intel_thread.1.dylib'
    Reason: tried: '/usr/local/lib/libiomp5.dylib' (no such file), '/usr/lib/libiomp5.dylib' (no such file).
    Intel MKL FATAL ERROR: Cannot load libmkl_intel_thread.1.dylib.
    logout
    Saving session...
    ...copying shared history...
    ...saving history...truncating history files...
    ...completed.

    为什么会缺库啊?!这件事情还不得而知,选择暂时放过自己,先来解决问题现象!这就引出了PyInstaller一个非常重要的机制——钩子!

    钩子🪝万岁

    浅百度一下,又在官网中看到有“Understanding PyInstaller Hooks”一节,大概感到有救。钩子是编程中用来实现可拓展性的一个常用技巧。钩子已在!缺什么钩什么!

    接下来看看PyInstsaller里具体怎么钩,抄 StackOverflow上的作业。

    1. 新建钩子脚本hook-numpy.py,把要钩的库列在里面

    from PyInstaller import log as logging
    from PyInstaller import compat

    from os import listdir

    mkldir = compat.base_prefix + "/lib"
    logger = logging.getLogger(name)
    logger.info("MKL installed as part of numpy, importing that!")
    binaries = [(mkldir + "/" + mkl, '.') for mkl in listdir(mkldir) if mkl.startswith('libmkl_')]

    1. 通过参数additional-hooks-dir告诉程序新增钩子的路径,参数clean是为了清除之前运行的缓存,多个香炉多个鬼,清一清没啥不好

    pyinstaller --additional-hooks-dir=. --clean --onefile tryPyinstaller.py

    双击应用,成功运行

    Last login: Sun Apr 9 15:02:31 on ttys008

    The default interactive shell is now zsh.
    To update your account to use zsh, please run chsh -s /bin/zsh.
    For more details, please visit https://support.apple.com/kb/HT208050.
    /Users/leixiaoyue/Code/YuePythonScript/tryPyinstaller/dist/tryPyinstaller/tryPyinstaller ; exit;
    (base) leixiaoyues-MacBook-Pro:~ leixiaoyue$ /Users/leixiaoyue/Code/YuePythonScript/tryPyinstaller/dist/tryPyinstaller/tryPyinstaller ; exit;
    6 / 3 = 2.0
    logout

    Saving session...
    ...copying shared history...
    ...saving history...truncating history files...
    ...completed.

    [Process completed]

    运行是真的慢……

    工程师的工具箱里又多了什么

    首先,是把所有依赖统统打包成应用的思路。这在帮完全外行的朋友写软件时超级有用,这样简单直接的思路以前还真没想到过。
    再就是又一次领略了🪝提供可拓展性的魅力。

    解决旧问题带来新问题

    为什么打包出来的程序运行那么那么慢……
    为什么打包numpy会缺libmkl_xxx一系列Math Kernal Library?
    Hook 真的是个好的命名吗?韩语후킹(hooking),日语フック(hook),直接用音译,大陆译作“钩子”,不能在亚洲圈获得统一的翻译,往往是命名不够准确的一个表现……

    相关文章

      网友评论

          本文标题:周日趣事:看看python脚本怎么打包成可执行文件(应用)

          本文链接:https://www.haomeiwen.com/subject/crhvddtx.html