Pyinstaller打包完整python项目 使用虚拟环境的python项目的打包
Pyinstaller基本使用方法
- 安装pyinstaller
pip install pyinstaller
- 切换到工作目录`
cd xxxxxxxxxxx
- 简单打包命令
可以用命令直接打包单文件,遇到项目时文件很多也可以用命令打包,但命令太长了过于繁杂,可以参考链接,通常用修改spec文件的模式,详见 :二 python项目的打包方法
Pyinstaller可以通过简单的命令进行python代码的打包工作,其基本的命令为:
pyinstaller -option xxx.py
假如项目启动入口为xxx.py,首先需要以管理员身份启动cmd,然后cd到xxx.py所在的文件夹
当我们使用命令行直接打包,即 pyinstaller -D xxx.py 时 :
1.生成默认的xxx.spec文件```python
2.直接根据默认的main.spec文件进行执行pyinstaller -D xxx.spec完成默认的打包
options常用参数(按需求选择):
-D 与 -F 相反用法,生成一个文件目录包含可执行文件和相关动态链接库和资源文件等,对于打包结果较大的项目,选用-D生成目录相比-F的打包方式,执行速度更快,但包含更加多的文件
-F 表示在 dist 文件夹下只生成单个可执行文件(内部包含所有依赖),不加默认会在 dist 生成一大堆依赖文件+可执行文件。
-w 表示去掉控制台窗口,如果你的程序是有界面的,可以不写这个参数,
-c 表示去掉窗框,使用控制台,推荐使用,会打印各种信息和log到控制台,加上这个参数生成的spec中的console=True
-p 表示自己定义需要加载的类路径,项目中包含多个自建模块的时候需要加上 -p aaa.py -p bbb.py -p ccc.py
-i 表示可执行文件的图标,后面跟图标的路径,可以自定义exe文件的图标,我尝试了好多次没成功
打包完毕后在 dist 文件夹下双击项目启动文件就可以执行了
二 Python完整项目的打包方法
参考:https://blog.csdn.net/weixin_42052836/article/details/82315118
以一个多文件和目录的Python项目为例,项目文件包含:1.Python源代码文件;2.图标资源文件;3.其它资源文件
以图中项目为例,Python源代码文件在多个目录下:bin, lib\app, lib\models, lib\views;图标资源文件在lib\icon目录下;其它资源文件在data目录下,包括文本文件,视频文件等等
1.生成 spec文件
为了实现自定义配置的打包:
第一步:需要生成启动文件默认的spec文件:(选择一个即可)
pyi-makespec -w xxx.py pyi-makespec -c xxx.py # 生成的spec文件中console=True,即需要打印到控制台
第二步:打开生成的spec文件,根据自己的项目结构和需求,修改其默认脚本,完成自定义打包需要的配置。
spec文件是一个python脚本,其默认的结构如下:
# -*- mode: python -*-block_cipher = Nonea = Analysis(['fastplot.py'],pathex=['D:\\install_test\\DAGUI-0.1\\bin'],binaries=[],datas=[],hiddenimports=[],hookspath=[],runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,cipher=block_cipher)
exe = EXE(pyz,a.scripts,exclude_binaries=True,name='fastplot',debug=False,strip=False,upx=True,console=False )
coll = COLLECT(exe,a.binaries,a.zipfiles,a.datas,strip=False,upx=True,name='fastplot')
spec文件中主要包含4个class: Analysis, PYZ, EXE和COLLECT.
Analysis以py文件为输入,它会分析py文件的依赖模块,并生成相应的信息
PYZ是一个.pyz的压缩包,包含程序运行需要的所有依赖
EXE根据上面两项生成
COLLECT生成其他部分的输出文件夹,COLLECT也可以没有
2.修改 spec文件
我们修改默认生成的spec文件,紫色为修改部分:
# -*- mode: python -*-
import sys
import os.path as osp
sys.setrecursionlimit(5000)block_cipher = None SETUP_DIR = 'D:\\install_test\\FASTPLOT\\'a = Analysis(['fastplot.py','frozen_dir.py','D:\\install_test\\FASTPLOT\\lib\\app\\start.py','D:\\install_test\\FASTPLOT\\lib\\models\\analysis_model.py','D:\\install_test\\FASTPLOT\\lib\\models\\datafile_model.py','D:\\install_test\\FASTPLOT\\lib\\models\\data_model.py','D:\\install_test\\FASTPLOT\\lib\\models\\figure_model.py','D:\\install_test\\FASTPLOT\\lib\\models\\time_model.py','D:\\install_test\\FASTPLOT\\lib\\models\\mathematics_model.py',
a) 打包 py文件
- 针对多目录多文件的python项目,打包时候需要将所有相关的py文件输入到Analysis类里。如上的spec脚本,将所有项目中的py文件路径以列表形式写入Analysis,这里为了说明混合使用了绝对路径和相对路径。这里面的所有列表项都必须是py文件!
- Analysis类中的pathex定义了打包的主目录,对于在此目录下的py文件可以只写文件名不写路径。
b) 打包 资源文件(其实就是复制资源到打包后文件夹对应位置)
- 资源文件包括打包的python项目使用的相关文件,如图标文件,文本文件等。
- 对于此类资源文件的打包需要设置Analysis的datas,将非py文件的路径与存放的文件夹名写在元组里,如:datas=[(SETUP_DIR+‘lib\icon’,‘lib\icon’),(SETUP_DIR+‘data’,‘data’)]
datas:
第一个参数:Python中的资源文件等非py类型文件的路径
第二个参数:打包后路径,要和路径中的文件夹名称相同
- 例子中的(SETUP_DIR+‘lib\icon’,‘lib\icon’)表示将D:\install_test\FASTPLOT\lib\icon文件夹以及其中内容打包后还放在打包路径下的lib\icon目录
- 假如项目某个文件夹打包时是空文件夹,但是运行中需要用到,比如log文件夹,即使将log地址写进datas中也不会生成,需要自己在代码里面用到某个文件夹去查看是否存在然后递归创建
c)Hidden import配置
- pyinstaller在进行打包时,会解析打包的python文件,自动寻找py源文件的依赖模块。但是pyinstaller解析模块时可能会遗漏某些模块(not visible to the analysis phase),造成打包后执行程序时出现类似No Module named xxx。
- 这时我们就需要在Analysis下hiddenimports中加入遗漏的模块,如例子中所示。
d)递归深度设置
- 在打包导入某些模块时,常会出现"RecursionError: maximum recursion depth exceeded"的错误,这可能是打包时出现了大量的递归超出了python预设的递归深度。因此需要在spec文件上添加递归深度的设置,设置一个足够大的值来保证打包的进行,即
import sys
sys.setrecursionlimit(5000)
e)去除不必要的模块import
- 有时需要让pyinstaller不打包某些用不到的模块,可通过在excludes=[]中添加此模块实现,如
excludes=['zmq']
3.使用spec执行打包命令
pyinstaller -D xxx.spec
打包生成两个文件目录build和dist:
build为临时文件目录完成打包后可以删除;
dist中存放打包的结果,可执行文件和其它程序运行的关联文件都在这个目录下,dist文件夹里包含了整个项目所需的代码和环境,可在其他电脑中进行使用
三 pipenv管理的虚拟环境下python项目的打包
当项目不使用默认的pip管理,采用更高级的pipenv管理的时候,是额外的一个虚拟环境,各种依赖都在虚拟幻境里,就需要切换到虚拟环境中操作,话不多说先上图:
该项目采用最新版 python 3.8.0
第一步:管理员方式打开cmd,cd到项目根目录
cd C:\Users\13154\Desktop\taibaorpa
第二步:创建项目的虚拟环境,如果已经有了,跳过这一步:
pipenv install
pipenv会根据项目的pipfile自动安装其中记载的所有依赖
第三步:进入虚拟环境
pipenv shell
进入后,路径最前面会出现虚拟环境
第四步:查看依赖是否安装成功,也可以不查看
pipenv graph
第五步:安装pyinstaller
pip install pyinstaller
第六步:生成spec
pyi-makespec -c main.py # 生成的spec文件中console=True,即需要打印到控制台
第七步:修改spec
修改后的spec
# -*- mode: python ; coding: utf-8 -*-
import sys
import os.path as osp
sys.setrecursionlimit(5000)
SETUP_DIR = 'C:\\Users\\13154\\Desktop\\taibaorpa\\'block_cipher = Nonea = Analysis(['main.py',SETUP_DIR+'asynctask.py',SETUP_DIR+'errors.py',SETUP_DIR+'file.py',SETUP_DIR+'msg.py',SETUP_DIR+'msg_pattern.py',SETUP_DIR+'pageon.py',SETUP_DIR+'report.py',SETUP_DIR+'script.py',SETUP_DIR+'settings.py',SETUP_DIR+'taibaorpa.py',SETUP_DIR+'taiboweb.py',SETUP_DIR+'webdriverhelper.py',SETUP_DIR+'wechat.py',],pathex=['C:\\Users\\13154\\Desktop\\taibaorpa'],binaries=[],datas=[(SETUP_DIR+'driver\\chrome','driver\\chrome'),(SETUP_DIR+'log\\screenshot_taiboweb','log\\screenshot_taiboweb'),(SETUP_DIR+'log\\screenshot_wechat','log\\screenshot_wechat'),(SETUP_DIR+'log\\wechat_files','log\\wechat_files'),(SETUP_DIR+'report','report'),(SETUP_DIR+'res\\img','res\\img'),(SETUP_DIR+'res\\vid','res\\vid'),(SETUP_DIR+'README.md','.')],hiddenimports=[],hookspath=[],runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,cipher=block_cipher)
exe = EXE(pyz,a.scripts,[],exclude_binaries=True,name='main',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,console=True )
coll = COLLECT(exe,a.binaries,a.zipfiles,a.datas,strip=False,upx=True,upx_exclude=[],name='main')
第八步:根据spec打包
pyinstaller -D main.spec
然后打开dist/main文件夹,里面的main.exe就是执行文件,双击能正确启动则打包成功
四 Python模块的打包问题
程序调用的很多包,在打包时候可能会出现一些问题,针对这写问题需要做一些处理才能保证打包的程序正常执行。
1.PyQt plugins缺失
使用PyQt编写UI交互界面的python代码在进行打包时可能会出现一些特别的问题。
执行使用了PyQt的打包程序,常会出现这样的错误,提示缺少Qt platfrom plugin “windows”,如下图
打包后程序运行后,使用png格式的图标可以正常显示,但使用的ico格式图标不显示(对于所有图标和关联文件都无法使用的情况涉及到路径问题,后文会另外解释)。
这两个错误产生的问题都是因为打包时没有将PyQt相关的动态链接库目录生成到打包目录下,因此可以通过将这些需要的文件目录拷贝到打包生成目录下,解决plugin缺失问题。以使用PyQt5编写的python软件打包为例,完成打包后的结果目录下包含PyQt5文件夹,将PyQt5\Qt\plugins下的所有内容(如下图)拷贝到打包结果目录。这样就可以解决PyQt plugins缺失的问题。
2.动态链接库缺失,执行程序出错:ImportError: DLL load failed: 找不到指定的模块
在打包过程中一般会有与此相关的warning提示(lib not found)无法找到这些动态链接库。例如在32位版本的打包中,可能会出现scipy模块相关的dll文件无法找到。
这时就需要在打包的spec文件中指定动态链接库路径,使其关联到打包后的路径中。
binaries=[(‘C:\Program Files\Python36-32\Lib\site-packages\scipy\extra-dll’,’.’)]
Analysis下的binaries是为打包文件添加二进制文件,缺失的动态链接库可以通过这种方式自动加入到打包路径中。
3.窗体风格变化问题
在某些情况下,如在精简环境下的python程序打包中,执行打包后的程序会出现窗体风格变为老式的win风格,这是由于打包时候PyQt的styles动态库没有找到。因此只需要在Python 目录下找到 Lib\site-packages\PyQt5\Qt\plugins\styles,将styles整个目录复制到打包结果目录。
4.当打包时出现:UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xce in position 122
可在打包的命令行中输入chcp 65001设置命令行显示utf-8字符,然后再执行打包命令。或者,修改pyinstaller包下的compat.py,根据报错对应的行将
out = out.decode(encoding)
改为
out = out.decode(encoding, ‘replace’)
5.执行打包命令时报错 ImportError: No module named ‘queue’
原因:尚不清楚
解决方法:如果该模块你用不到,可以在执行打包命令时用 --hidden-import 不打包进去。如果程序中需要该模块,在主文件最上面写上 improt queue
6.打包命令执行成功,但双击可执行程序弹出报错窗口failed to excute script xxx
原因:打包时内部缺少了某个依赖,这时需要看看控制台打印了什么报错信息,打包时加了 -w 参数的请再打包一次记得去掉 -w以便于查看log信息
现象:基本都是在控制台上发现报错 No module named ‘xxxxx’,如 No module named ‘queue’ 或者 ModuleNotFoundError: No module named ‘PyQt5.sip’
解决方法1:同2,如果该模块你用不到,可以在执行打包命令时用 --hidden-import 不打包进去。如果程序中需要该模块,在主文件最上面写上 improt xxxxx。如 import queue 或 import PyQt5.sip
解决方法2:我用pipenv管理的项目,但是在真实环境下打包,打包好后运行出现这个,重新走 第二章 中流程,成功打包
7.冻结打包路径
执行打包后的程序,经常会出现程序使用的图标无法显示,程序使用的关联文件无法关联。或者,在打包的本机上运行正常,但是将打包后的程序放到其它机器上就有问题。这些现象都很有可能是由程序使用的文件路径发生改变产生的,因此在打包时候我们需要根据执行路径进行路径“冻结”。
1.使用绝对路径
在python代码中使用绝对路径调用外部文件可以保证打包时候路径可追溯,因此在本机上运行打包后程序基本没问题。但是当本机上对应路径的资源文件被改变,或者将打包程序应用到别的机器,都会出现搜索不到资源文件的问题。这种方式不是合适的打包发布python软件的方式。
2.使用冻结路径
增加一个py文件,例如叫frozen_dir.py
-- coding: utf-8 --
“”"
Created on Sat Aug 25 22:41:09 2018
frozen dir
@author: yanhua
“”"
import sys
import os
def app_path():
“”“Returns the base application path.”""
if hasattr(sys, ‘frozen’):
# Handles PyInstaller
return os.path.dirname(sys.executable)
return os.path.dirname(file)
其中的app_path()函数返回一个程序的执行路径,为了方便我们将此文件放在项目文件的根目录,通过这种方式建立了相对路径的关系。
源代码中使用路径时,以app_path()的返回值作为基准路径,其它路径都是其相对路径。以本文中使用的python项目打包为例,如下所示
import frozen_dir
SETUP_DIR = frozen_dir.app_path()
FONT_MSYH = matplotlib.font_manager.FontProperties(
fname = SETUP_DIR + r’\data\fonts\msyh.ttf’,
size = 8)
DIR_HELP_DOC = SETUP_DIR + r’\data\docs’
DIR_HELP_VIDEO = SETUP_DIR + r’\data\videos’
通过冻结路径,使用了基准目录下的data目录下的fonts, docs, videos。
主程序中也做了类似的调整,改变其设置路径方法
import frozen_dir
SETUP_DIR = frozen_dir.app_path()+r’\lib’
sys.path.append(SETUP_DIR)
使用这样的方法进行打包,打包后的可执行程序就可以在其它机器上运行。
五 其它问题
由于操作系统和运行环境的不同,pyinstaller打包中还可能遇到很多其它问题,最后总结一些我在打包中遇到的其它坑:
1.权限问题
通常时在打包时出现的某些文件拒绝访问或没有权限执行某些操作等。解决这个的方法一般有这几个方面:
a)使用管理员权限运行cmd或其它命令行窗口
b)关闭杀毒软件
c)使用完全权限的管理员账户
2.中文路径
pyinstaller打包后的路径使用中文没有问题,不过为了减少打包时候出错的可能,尽量将打包使用的资源文件和代码文件路径设置为英文。
3.打包后文件的大小
通常python打包为可执行文件都会得到一个较大的包,这是无法避免的,但是我们还是可以通过一些方法来尽量精简打包后的执行程序:
a)在代码中减少不必要的import,如from xxx import *
b)在精简的运行环境(如原生python环境)下打包,缺什么包就下什么包,避免不必要的python包被打包入程序。尤其是anaconda这样的集成环境下打包的结果会大很多。
c)使用UPX
Pyinstaller打包完整python项目 使用虚拟环境的python项目的打包相关推荐
- Python VScode 配置虚拟环境(virtualenv)
Python 虚拟环境 Python 之所以强大,除了语言本身的特性外,更重要的是拥有无所不及的第三方库.强大的软件库,让开发者将精力集中在业务上,而避免重复造轮子的浪费.但众多的软件库,形成了复杂的 ...
- Python中fastapi构建的web项目使用pyinstaller打包为exe文件
假设当前已经使用fastapi构建了一个web项目,项目结构为: 如果我们想使用pyinstaller对此web项目进行打包为exe文件,则需要在项目的跟目录下面执行下述命令先安装pyinstalle ...
- 使用pipenv建立虚拟环境解决python打包exe文件过大的问题(附打包带图标,多个py文件打包exe)
我们编写的程序可以发给其他小伙伴使用,但是其他小伙伴不一定安装有python.这时候就需要用到打包啦.打包可以将程序打包成exe文件.然后小伙伴在windows平台里就可以运行(无需python).直 ...
- python快速编程入门课后程序题答案-Python编程从零基础到项目实战 完整PPT+习题答案...
Python编程从零基础到项目实战是一本介绍Python相关知识的Python基础教程,内容涉及算法.Python数据分析.图形处理.Web开发.科学计算.项目管理.人工智能.Python爬虫等.其中 ...
- docker 打包部署 python项目_Docker如何部署Python项目的实现详解
Docker 是一个开源项目,为开发人员和系统管理员提供了一个开放平台,可以将应用程序构建.打包为一个轻量级容器,并在任何地方运行.Docker 会在软件容器中自动部署应用程序. 在本篇中,我将介绍如 ...
- 零基础学python实战答案-Python编程从零基础到项目实战 完整PPT+习题答案
Python编程从零基础到项目实战是一本介绍Python相关知识的Python基础教程,内容涉及算法.Python数据分析.图形处理.Web开发.科学计算.项目管理.人工智能.Python爬虫等.其中 ...
- pyinstaller打包生成的exe文件并使用python终止后台的exe程序运行
pyinstaller打包生成的exe文件并使用python终止后台的exe程序运行 目录 pyinstaller打包生成的exe文件并使用python终止后台的exe程序运行 #pyinstalle ...
- python代码写完怎么运行-Python 项目代码写完了,然后怎么打包和发布?
你把你的代码写完了,是不是要给别人使用下,怎么打包你的项目代码呢? 喂,开源么? 接下来小帅b就跟你说说,如何打包你的代码. 就拿我们上次演示的 用 Python 开发一个 「个人计划 todolis ...
- php代码里怎么写html代码_菜鸟青铜变白银!Python 项目代码写完了,然后怎么打包和发布?...
你把你的代码写完了,是不是要给别人使用下,怎么打包你的项目代码呢?喂,开源么?接下来小帅b就跟你说说,如何打包你的代码.就拿我们上次演示的 todo为例,写完代码之后,代码的目录是这样的: 在 tod ...
最新文章
- 叹西安2014中秋节雨天
- SQL Server游标的使用
- CAN接口芯片TJF1051T/3波形
- MobileGestalt.h 头文件
- [PAT乙级]1016 部分A+B
- 08_MySQL DQL_SQL99标准中的多表查询(内连接)
- 面向多媒体 linux 版本,基于MX Linux 的 AV Linux 新版发布,此AV非彼AV
- executable file and DLL
- Typora列表段落(list paragraph)的行间距
- 循环机换变速箱油教程_变速箱油多久换?很多老司机都可能不知道
- 停止运行_部门动态丨供水运行不能中断,保障维修从未停止
- 在外置移动硬盘中安装Win10
- 植物大战僵尸修改向日葵无限吐阳光详细步骤~包含排除不符合条件的地址的讲解,以及如何观察地址情况等
- 关于计算球体体积的Java代码啾咪~
- 2021年度IT吃瓜指南
- leveldb 详解
- TestNG修改reportNG输出description
- 高考录取系统的模拟(1)——成绩的模拟生成程序
- 从十亿光年到0.1飞米
- 王者荣耀最失败的英雄是?失败英雄应该有哪些特征?
热门文章
- 图解Java数据结构之环形链表
- 飞机躲避小游戏---是男人就撑100秒的制作
- 纳税人信息0服务器信息1,​财务报表提示没有申报清册信息是什么原因
- 解决每次启动都弹出UAC对话框
- 爬取《斗破苍穹》小说全文
- [转载]多普达手机全揭露
- Macromedia FlashPaper 2的安装方法(XP和Win7)
- Cygwin踩坑记录(五)- 下载sdkman提示OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to sdkman:443
- 计算机未来发展趋势论述,浅述未来计算机的发展趋势论文
- linux 备份文件脚本,linux 下shell脚本备份文件(示例代码)