这是一个关于如何利用pyinstaller去打包一个完整的项目(其中包括环境依赖和exe可执行文件)的主要过程。
通过pyinstaller打包好后,在其他电脑中运行.exe可执行程序时不需要配置相关环境依赖即可顺利运行。
此外,还分享了在打包过程和打包完成后以及在其他电脑上运行等出现的一些问题的解决方法。
pip install pyinstaller
–h,–help | 模块的帮助信息 |
---|---|
-F | 产生单个可执行文件 |
-D | 产生一个目录(包含多个文件)作为可执行文件 |
-w | exe程序运行时是否显示命令符窗口 |
–hidden-import module-name | 隐藏不需要的导入模块 |
多隐藏方法 --hidden-import 'xxx,xxx,xxx'
详细的pyinstaller命令介绍
对于打包一个完整项目,首先需要一个干净的环境(包括新建的conda环境或没有安装第三方库的全局python系统环境)。
为了避免打包时出现一些不必要的错误,这里推荐没有安装第三方库的全局python系统环境。(仅为推荐,新建一个conda环境也行).
另外,请确保路径中不包含中文等特殊字符。
pyinstaller -option xxx.py
基本流程:
C:\Users\user-name>E:
–> E:\>cd test
(这里推荐在文件资源管理器中进入到项目的文件夹中,在路径输入栏中输入cmd直接进入)pyinstaller -D test.py
pyinstaller -D -w xxx.py
这是缺少第三方库,看见这个就可以直接用pip安装这个库
这个大多数不会影响程序的运行,可以忽略
只要程序能正常运行,这个警告可以忽略
一般是由于scikit-image这个库导致的。由于所使用的设备缺少某些.dll文件或缺少某些第三方库的依赖文件。如,缺少了C++运行库,可下载vc_redistx64.exe
主要是因为一些库没有安装到或者打包时pyinstaller强行打包了一些不必要的库。
解决方法:这个问题主要在基本流程的第5步中常出现。要是按照基本流程来做,只需要打开.exe文件,通过查看命令符窗口报的错来解决(通常窗口消失快,可通过windows截屏快捷键__win + Shift + S__来截取报错内容))。或者,以有窗口模式下打包项目,之后将.exe文件托入命令符窗口中来查看错误。(再或者,用手机录制运行时的整个过程)
例如提示no module name “xxx”,先检查是否是需要的库,若是不必要的库可通过以下命令重新打包(例如库名字为scipy.xxx.xxx) pyinstaller -D test.py --hidden-import scipy.xxx.xxx
主要情况为,使用含有深度学习模型进行预测的.exe可执行程序时,同时出现多窗口(例如有包含qt时会打开多个窗口)。解决方法:新建一个py文件命名为multiprocessing_win.py,写入以下代码。
import sys
import multiprocessing
try:
if sys.platform.startswith('win'):
import multiprocessing.popen_spawn_win32 as forking
else:
import multiprocessing.popen_fork as forking
except ImportError:
import multiprocessing.forking as forking
if sys.platform.startswith('win'):
class _Popen(forking.Popen):
def __init__(self, *args, **kw):
if hasattr(sys, 'frozen'):
os.putenv('_MEIPASS2', sys._MEIPASS)
try:
super(_Popen, self).__init__(*args, **kw)
finally:
if hasattr(sys, 'frozen'):
if hasattr(os, 'unsetenv'):
os.unsetenv('_MEIPASS2')
else:
os.putenv('_MEIPASS2', '')
forking.Popen = _Popen
之后将这个文件放到项目的根目录中,并在执行多进程的py文件中写入
import multiprocessing_win
import multiprocessing
按以上要求做好后,在实现图形界面的py文件中或主py文件中按以下例子加入
import multiprocessing_win
import multiprocessing
if __name__ == '__main__':
multiprocessing.freeze_support()
app.run()
在pythonxx/lib目录下,找到pyinstaller/hooks/hook-tkinter.py
通过搜索找到path_to_tcl,再按以下例子修改(主要为添加了and ‘Python’ not in path_to_tcl来防止路径丢失报错)
path_to_tcl = bins[0][1]
#if 'Library/Frameworks' in path_to_tcl:
if 'Library/Frameworks' in path_to_tcl and 'Python' not in path_to_tcl:
主要为python的ssl证书过期的原因。
解决方法主要有:
我的Github地址:https://github.com/ReverseSacle