[√]pyinstaller打包的exe运行报错,找不到库

77 阅读2分钟

PyInstaller 是一个用于将 Python 程序打包成独立可执行文件的工具。

使用 PyInstaller 可以将 Python 脚本及其所有依赖项(包括第三方库和资源文件)打包到一个单个的可执行文件中,这样用户就不需要安装 Python 解释器或其他依赖项即可运行该程序。

PyInstaller 支持跨平台,并可以在 Windows、macOS 和 Linux 上进行打包。它能将 Python 程序打包为原生的可执行文件(如EXE、APP或ELF),从而实现了更好的用户体验和便携性。

pyinstaller之后报错

Traceback (most recent call last):
  File "generator.py", line 1574, in <module>
    main()
  File "generator.py", line 1569, in main
    generator.generate_code()
  File "generator.py", line 1204, in generate_code
   顶层逻辑
    layout_h = Template(file=os.path.join(self.target, "templates", "layout_head.h"), searchList=[self])
  File "site-packages\Cheetah\Template.py", line 1259, in __init__
  File "site-packages\Cheetah\Template.py", line 1553, in _compile
  File "site-packages\Cheetah\Template.py", line 788, in compile
  看到它会拼接一个文件,这个路径是以_分割,目录很明显不是exe的
  File "_proj_cocos_binding_static_targets_lua_templates_layout_head_h.py", line 21, in <module>
ImportError: No module named DummyTransaction

在调用栈中发现路径分隔符有异常

H:\\proj\\cocos-binding/static\\targets\\lua
               ↑ 这里的横杠转换出现了问题
    _proj_cocos_binding_static_targets_lua

但是底层Template在处理的时候会正确转换路径分隔符 image.png

问题出在这个convertTmplPathToModuleName函数 image.png

image.png 折腾了一圈,发现好像跟这个路径分隔符没有关系,因为我这本地正常的版本也是这个转换逻辑,这里只是为了防止出现特殊字符串

原因

报错提示的代码好像是临时生成的,所以报错后我一直在本机找不到这个文件。

报错的21行代码为

LOAD_CONST(-1), LOAD_CONST(('*',)), IMPORT_NAME(Cheetah.DummyTransaction), IMPORT_STAR

这个报错也就对上了,的确是有这个文件,需要确认下pyinstaller之后是否有这个文件

image.png

解包之后发现还真的就没有Cheet.DummyTransaction这个文件

image.png

感觉是pyinstaller的问题,我使用的pyinstaller版本是3.6,看了文档--hidden-import可以强制将某些lib打包进去,

--hidden-import Cheetah

发现这样没有任何效果,exe运行仍旧提示找不到DummyTransaction模块,解包后的确还是没有,文档上也没有说的更清楚,抱着试试看的态度

--hidden-import Cheetah.DummyTransaction

这样的确是可以了,以防万一,所有的都加上

--hidden-import Cheetah.DummyTransaction --hidden-import PyYAML

pyinstaller并不会把整个lib的代码全部放进去,比如这个cheet库,我发现他会分析你代码中使用到的库的某些工具,仅仅把这些用到的库工具打包进去,这么做也是为了尽可能的减小包体,如果代码中有动态加载的逻辑,pyinstaller就无法识别到,这时就需要--hidden-import打包选项了。