1、问题描述
使用pyinstaller -F ***.spec命令打包,打包过程无报错信息,生成可执行文件(.exe),双击运行报错,如下图:
2、查找原因
(1)百度,查看打包文件(build/***/warn-***.txt)
百度后,基本都是两类,一类是打包时未能正确导入一些包,但是这类基本在打包过程就会报错,还有一类就是去找打包生成的一个warn文本。
我找到了该文件,打开研究,也没研究出个所以然,把里面一些感觉像的信息拿出来单独百度,可是也处理不了。
(2)单独排查
因为这个项目之前是可以正常打包的,因此我怀疑会不会是新增的文件存在问题。
我手动回退版本,回到之前可以打包的版本,重新打包,发现一切正常。
然后逐步添加增加的文件,一步步调试,最终定位到了一个文件conf.py
以下是文件源码:
# -*- coding: utf8 -*-
import os
import yaml
def _get_yaml():
"""
解析yaml
:return: s 字典
"""
path = os.path.join(os.path.dirname(__file__) + '/config.yaml')
f = open(path, mode='r', encoding='UTF-8')
s = yaml.load(f)
f.close()
return s.decode() if isinstance(s, bytes) else s
这是一个读取yaml配置文件的方法,之前百度直接copy了别人的代码。
结合之前打包的经验,我留意到这里有一个读取文件的方法,我怀疑是文件路径的问题,在打包后,这个路径失效了。
我把路径直接改为相对路径和绝对路径下尝试了,发现在绝对路径下是可以运行的。
可是我打包的时候是要打包config.yaml这个文件的,我不想后面部署时,还要把这个文件单独放到一个指定路径。
我尝试使用打包读取资源的方法来读取这个文件,结果成功了!
3、解决方案
修改如下:
# -*- coding: utf8 -*-
from util import ResourcePath
import yaml
def _get_yaml():
"""
解析yaml
:return: s 字典
"""
f = open(ResourcePath.resource_path('config/config.yaml'), mode='r', encoding='UTF-8')
s = yaml.load(f)
f.close()
return s.decode() if isinstance(s, bytes) else s
关联的ResourcePath.py文件源码如下:
import os
import sys
def resource_path(relative_path):
"""
定义一个读取相对路径的函数
"""
if hasattr(sys, "_MEIPASS"):
base_path = sys._MEIPASS
else:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
此外,打包的文件(.spec)也要修改:
Analysis里的datas参数添加('config','config')