windows 10
python 3.10.10
pip 23.0.1
pyinstaller 5.9.0
1 2 3 4 5 6 7 8 9 |
# 先要通过pip安装全部用到的库,测试flask项目正常运行。 pip3 install flask pip3 install flask-wtf pip3 install flask-mail pip3 install email_validator pip3 install flask-sqlalchemy pip3 install bootstrap-flask # 最后 pip3 install pyinstaller |
说明:
如果要生成windows系统上的exe程序,就把项目源码放到windows系统上,并进行如下操作
如果要生成macos系统上的app程序,就把项目源码放到苹果电脑macos系统上,并进行如下操作
1.最简打包
cmd进入 项目根路径
入口函数文件为app.py
执行
1 |
pyinstaller -F -w -i ico-app.ico app.py |
得到 build文件夹、dist文件夹、app.spec文件
-w 参数表示 生成的exe程序不显示控制台。如果需要随时查看运行情况,就不使用此参数。
-i ico.ico 表示,exe文件的图标为ico.ico。如果不设置默认为python图标。
如果是一般的python程序,仅执行这一步即可。
2.flask资源文件配置
接上一步,修改app.spec文件,配置flask服务器程序所需的资源文件。
如果足够熟悉.spec文件,能够手写,也可以直接从这一步开始。
核心配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
a = Analysis( ['app.py'], # flask服务器入口文件 datas=[ # 要打包进exe的资源文件。注意结合动态路径进行调用 ('static/css/*.*', 'static/css'), # 元组第一项是源文件,第二项是解压释放后的文件名 ('static/js/*.*', 'static/js'), # 多级目录也须添加 ('static/*.*', 'static'), # 保存 自定义的目录和文件 ('templates/*.*', 'templates')], # 以及flask默认的目录 ) exe = EXE( name='app', # exe文件名称。默认是入口文件名称,可自定义。 debug=False, upx=True, # 启用文件压缩 upx_exclude=[], # upx压缩程序的路径。不指定则不进行压缩 runtime_tmpdir=None, console=True, # 如果第一步使用了-w参数,这里就为False,否则为True-程序运行后显示控制台 icon=['ico.ico'], # exe文件图标。第一步-i时使用的图标文件,可修改。 ) |
注意资源文件的访问,如果代码中使用的是
绝对路径,那么exe程序启动也会去找绝对路径;
相对路径,那么exe程序启动会去找相对自身的路径;
如此都不灵活,程序到其它电脑时,既需要exe程序也须要路径关系匹配的资源文件。
最好是只复制exe文件到其它电脑就能正常运行,这就须要在代码中通过动态路径访问资源文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import os, sys # exe程序解压后的文件,动态路径函数。根据启动方式不同(py源文件、exe二进制程序)得到不同的路径 def resource_p(relative_p): current_directory = os.path.dirname(os.path.abspath(__file__)) + '/../' # app.py的目录 base_p = getattr(sys, '_MEIPASS', current_directory) # getattr(src, key, default) 如果src存在key属性(方法)则返回key对应的值(方法地址)否则返回default值。_MEIPASS是sys内置的临时目录。 return os.path.join(base_p, relative_p) # 调用示例 p = resource_p('static') with open(p + "/picture.txt", 'r', encoding='utf-8') as f: for line in f.readlines(): line = line.strip() |
3.打包flask项目
执行
1 |
pyinstaller app.spec |
这一步后,在dist文件夹中生成新的“app.exe”最终二进制程序-如果app.spec中没有设置新的名称。
运行app.exe,如图,和vscode中直接运行源文件启动程序比较:
exe程序运行时解压释放的文件路径:
4.手动终止flask程序
上一步中,直接关闭app.exe的控制台窗口即可。
vscode中启动的服务器,除了“Kill Terminal”,还可以通过flask的端口号找到对应进程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# macos 手动终止flask: $ sudo lsof -i tcp:60931 # COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME # Python 50711 moonmen 3u IPv4 0x98768b298b3b7b05 0t0 TCP *:60931 (LISTEN) # Python 50712 moonmen 3u IPv4 0x98768b298b3b7b05 0t0 TCP *:60931 (LISTEN) # Python 50712 moonmen 4u IPv4 0x98768b298b3b7b05 0t0 TCP *:60931 (LISTEN) $ sudo kill -9 50712 # windows 手动终止flask: > netstat -aon|findstr "60931" # NODE NAME PID # TCP 0.0.0.0:60931 0.0.0.0:0 LISTENING 8004 > taskkill -F /pid 8004 # 结束进程 # 成功: 已终止 PID 为 8004 的进程。 # 或 > tasklist|findstr "8004" # 查看此pid的程序,如下是python.exe # python.exe 8004 Console 1 31,372 K > taskkill /im python.exe # 终止程序 |
5.可能出现的错误
打包出错:pyinstaller IndexError: tuple index out of range
修改:D:/apps/Python310/Lib/dis.py
1 2 3 4 5 6 7 8 9 10 11 |
def _unpack_opargs(code): extended_arg = 0 for i in range(0, len(code), 2): op = code[i] if op >= HAVE_ARGUMENT: arg = code[i+1] | extended_arg extended_arg = (arg << 8) if op == EXTENDED_ARG else 0 else: arg = None extended_arg = 0 ######################## 加这一句 yield (i, op, arg) |
- end
本文由崔维友 威格灵 cuiweiyou vigiles cuiweiyou 原创,转载请注明出处:http://www.gaohaiyan.com/4271.html
承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设