当前位置: 首页 > news >正文

streamlit+wordcloud使用pyinstaller打包遇到的一些坑

说明

相比常规的python程序打包,streamlit应用打包需要额外加一层壳,常规app.py应用运行直接使用

python app.py

就可以运行程序了,但streamlit应用是需要通过streamlit命令来运行

streamlit app.py

所以使用常规的pyinstaller app.py打包是不可行滴。
注:这里就默认大家都把python环境和streamlit环境都安装好了

正确打包姿势

此次操作工作目录结构如下
在这里插入图片描述

1、同workdir下创建一个hooks目录并创建一个hook_app.py(命名可以自定义,只是在打包的时候能找到就行)文件,hook_app.py文件内容如下:

from PyInstaller.utils.hooks import copy_metadatadatas = copy_metadata("streamlit")

2、与app.py文件同级创建一个run_app.py文件,具体内容如下

import streamlit.web.cli as stcli
import os, sysdef resolve_path(path):resolved_path = os.path.abspath(os.path.join(os.getcwd(), path))return resolved_pathif __name__ == "__main__":sys.argv = ["streamlit","run",resolve_path("app.py"),"--global.developmentMode=false",]sys.exit(stcli.main())

3、首次打包

直接通过命令进行首次打包

pyinstaller --onefile --additional-hooks-dir=./hooks run_app.py --clean

执行完后会在run_app.py同级下生成run_app.spec文件,具体内容如下

# -*- mode: python ; coding: utf-8 -*-a = Analysis(['run_app.py'],pathex=[],binaries=[],datas=[('static/*', './static')],hiddenimports=['wordcloud'],hookspath=['./hooks'],hooksconfig={},runtime_hooks=[],excludes=[],noarchive=False,
)
pyz = PYZ(a.pure)exe = EXE(pyz,a.scripts,a.binaries,a.datas,[],name='run_app',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,upx_exclude=[],runtime_tmpdir=None,console=True,disable_windowed_traceback=False,argv_emulation=False,target_arch=None,codesign_identity=None,entitlements_file=None,
)

到这里首次打包是成功的,但此时生成的exe文件还用不了,别问为啥,问就是有问题,咱继续接着说。

3、二次打包

根据首次打包生成的run_app.spec文件我进行调整,需要将一些环境以及一些所需的静态文件一同打包进去,修改后内容如下所示

# -*- mode: python ; coding: utf-8 -*-
from PyInstaller.utils.hooks import copy_metadatadatas=[("./site-packages/altair/vegalite/v5/schema/vega-lite-schema.json","./altair/vegalite/v4/schema/"),("./site-packages/streamlit//static","./streamlit/static"),("./site-packages/streamlit/runtime","./streamlit/runtime"),("./site-packages/wordcloud","./wordcloud"),('./static/*', './static')]
datas+=copy_metadata('streamlit')a = Analysis(['run_app.py'],pathex=[],binaries=[],datas=datas,hiddenimports=['wordcloud'],hookspath=['./hooks'],hooksconfig={},runtime_hooks=[],excludes=[],noarchive=False,
)
pyz = PYZ(a.pure)exe = EXE(pyz,a.scripts,a.binaries,a.datas,[],name='run_app',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,upx_exclude=[],runtime_tmpdir=None,console=True,disable_windowed_traceback=False,argv_emulation=False,target_arch=None,codesign_identity=None,entitlements_file=None,
)

粗略说明下:这里只是对datas里的内容进行额外处理了,将本地或是指定py环境下的altair、streamlit、wordcloud相关依赖环境打包到exe中
内容修改好后咱直接使用以下命令进行二次打包

pyinstaller run_app.spec --clean

等打包完毕后dist目录下就会生成一个run_app.exe 文件了,这时候不要高兴太早,直接运行也是会有问题滴,这里我们需要把app.py文件复制到生成的run_app.exe所在目录下,如图所示:
在这里插入图片描述
这时候咱再运行run_app.exe,如果你看到了以结果,那么恭喜你,你已经成功了,如果报错了那就请耐心的看看错误信息仔细排查下,或是看看我接下来说的一问题看你是否踩坑了
在这里插入图片描述

遇见问题

1、程序启动报错提示streamlit模块找不到

检查下有没有hook_app.py 文件,以及内容里是否有定义copy_metadata(“streamlit”),如果没有就请加上。加上后重复我以上打包步骤再试试,如果还是提示没有就检查下首次打包后生成的run_app.spec文件有没有正常修改为我提供的实例那样,如果改了就再确定下datas定义里设置的路径是否可用
在这里插入图片描述

2、程序启动后wordclould模块找不到

检查下首次打包生成的run_app.spec文件修改有没有遗漏下图所示的设置
在这里插入图片描述
这里需要把wordcloud模块引入

3、程序启动后词云生成失败,导致页面词云图片为空

这里需要引入一些字体文件,打包好后把字体静态文件放置到与exe程序同级目录下,如下图所示
在这里插入图片描述
在这里插入图片描述
放好了重启exe程序即可验证,效果如下图
在这里插入图片描述
附上一键打包脚本(选择性使用):

import os
import shutil
import subprocessWORK_DIR = os.getcwd()def package():build_path = os.path.join(WORK_DIR,'build')dist_path = os.path.join(WORK_DIR,'dist')if os.path.exists(build_path):shutil.rmtree(build_path)if os.path.exists(dist_path):shutil.rmtree(dist_path)try:# 构建 PyInstaller 命令cmd = ['pyinstaller','--onefile','--hidden-import=wordcloud','--add-data', 'static/*;./static','--additional-hooks-dir=./hooks','run_app.py','--clean']print("首次打包cmd:{}".format(cmd))result = subprocess.run(cmd, capture_output=True, text=True)print("首次打包结果:{}".format(result))if result.returncode == 0:os.remove(os.path.join(WORK_DIR,'run_app.spec'))source_spec = os.path.join(WORK_DIR,'package_app_spec.txt')dest_spec = os.path.join(WORK_DIR,'run_app.spec')with open(dest_spec,'w') as f:passshutil.copy(source_spec, dest_spec)cmd_final = ['pyinstaller','run_app.spec','--clean']final_result = subprocess.run(cmd_final, capture_output=True, text=True)if final_result.returncode == 0:app_path = os.path.join(WORK_DIR,'app.py')dest_app_path = os.path.join(dist_path,'app.py')with open(dest_app_path,'w') as f:passshutil.copy2(app_path,dest_app_path)shutil.copytree(os.path.join(WORK_DIR,'static'),  os.path.join(dist_path,'static'))print("打包成功")else:print("最后打包失败:{}".format(final_result))else:print("首次打包失败:{}".format(result))except Exception as e:print(e)if __name__ == "__main__":package()

如果按照以上步骤依旧解决不了您的问题,滴滴我哈!

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • boost库容器之Circular Buffer功能介绍,及使用示例
  • 神经网络微调技术全解(04)-- Prompt Tuning-可训练提示(Learnable Prompts)
  • 第十章 rust网络编程基础
  • 基于web的停车场管理系统设计与实现-计算机毕设 附源码 16856
  • Kafka·概述
  • 【计算机网络】计算机网络的分层结构
  • 【深度学习与NLP】——深度卷积神经网络AlexNet
  • 华为eNSP:静态路由配置、浮动路由配置
  • 阿里云OSS文件存储
  • 初识C++(8.27)
  • CentOS 7的yum源更换为国内源
  • 【设计模式】简单工厂模式
  • Ai+若依(页面调整--去除若依的各种痕迹,采用自己的):【07篇】
  • Qt_信号槽机制
  • UnrealEngine学习(01):安装虚幻引擎
  • 10个确保微服务与容器安全的最佳实践
  • 2019年如何成为全栈工程师?
  • conda常用的命令
  • HomeBrew常规使用教程
  • JavaScript-Array类型
  • MobX
  • python3 使用 asyncio 代替线程
  • SegmentFault 2015 Top Rank
  • SpriteKit 技巧之添加背景图片
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 对象管理器(defineProperty)学习笔记
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • ​secrets --- 生成管理密码的安全随机数​
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (solr系列:一)使用tomcat部署solr服务
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (附源码)计算机毕业设计高校学生选课系统
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (转)Scala的“=”符号简介
  • (转)程序员疫苗:代码注入
  • (转)原始图像数据和PDF中的图像数据
  • (转载)虚函数剖析
  • *** 2003
  • .Net Core 微服务之Consul(二)-集群搭建
  • .Net CoreRabbitMQ消息存储可靠机制
  • .Net 执行Linux下多行shell命令方法
  • .Net环境下的缓存技术介绍
  • .NET开源、简单、实用的数据库文档生成工具
  • .NET是什么
  • ?.的用法
  • []AT 指令 收发短信和GPRS上网 SIM508/548
  • [Android] 修改设备访问权限
  • [C\C++]读入优化【技巧】