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

news/2024/9/19 16:36:37/ 标签: python, 学习方法, streamlit, pyinstaller, wordcloud

说明

相比常规的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文件内容如下:

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

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

python">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文件,具体内容如下

python"># -*- 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文件我进行调整,需要将一些环境以及一些所需的静态文件一同打包进去,修改后内容如下所示

python"># -*- 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、streamlitwordcloud相关依赖环境打包到exe中
内容修改好后咱直接使用以下命令进行二次打包

pyinstaller run_app.spec --clean

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

遇见问题

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

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

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

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

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

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

python">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()

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


http://www.ppmy.cn/news/1518928.html

相关文章

(备份)常用ASCII 8*8 点阵 以及查询显示字符的点阵

图片 #include "driver/spi_master.h" #include "driver/gpio.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "string.h" #include "driver/i2c.h" #include "esp_rom_sys.h"…

Java分布式架构知识体系及知识体系图

Java分布式架构整体知识体系是一个庞大而复杂的领域,它涵盖了多个方面,旨在帮助开发者构建高性能、高可用、可扩展的分布式系统。以下是对Java分布式架构整体知识体系的概述: 一、分布式理论基础 CAP理论: 一致性(Con…

Java算法之Gnome 排序

简介 Gnome 排序,又称为双向插入排序或鸡尾酒排序,是一种改进的插入排序算法。它在每次迭代中不仅将最小的元素移动到前面,同时也将最大的元素移动到后面。这种排序算法在每次迭代中同时向两个方向进行移动,因此得名。 算法步骤…

如何开发针对不平衡分类的成本敏感神经网络 python

如何开发针对不平衡分类的成本敏感神经网络 深度学习神经网络是一类灵活的机器学习算法,可以在各种问题上表现良好。 神经网络使用误差反向传播算法进行训练,该算法涉及计算模型在训练数据集上产生的误差,并根据这些误差的比例更新模型权重…

240831-Qwen2-VL-7B/2B部署测试

A. 运行效果 B. 配置部署 如果可以执行下面就执行下面: pip install githttps://github.com/huggingface/transformers accelerate否则分开执行 git clone https://github.com/huggingface/transformers cd transformers pip install . accelerate随后&#xff0…

k8s-pod 实战一 (创建pod,启动命令,参数,pod故障排除,拉取命令)

1. 创建一个Pod Pod 是 Kubernetes 中最小的部署单元。它可以包含一个或多个容器。下面是一个简单的 YAML 文件,用于创建一个包含 Nginx 容器的 Pod。 示例 YAML 文件 (nginx-pod.yaml) apiVersion: v1 kind: Pod metadata:name: nginx-pod spec:containers:- name: nginx-…

STM32(八):定时器——输入捕获实验

目录 输入捕获模式测频率: 结构图: 步骤: 部分函数详解: 源码: PWMI模式测频率占空比: 结构图: ​编辑 举例说明 源码: 输入捕获模式测频率: 结构图&#xf…

C#中List集合使用Remove方法详解——List使用Remove方法需要注意的坑?

目录 一、基本使用 1、简单类型的例子 2、复杂类型的例子 二、思考 三、深度解析 四、正确的使用方式 1、重写 Equals 和 GetHashCode 2、使用 LINQ 的 FirstOrDefault 方法 五、性能考虑 六、注意事项 总结 在C#中&#xff0c;List<T> 是一个常用的数据结构&…

第四章 Java核心类库 第三节 集合框架

1. 集合框架概述与结构 首先&#xff0c;我们来简单了解一下Java集合框架的概述和结构。 集合框架的定义&#xff1a;Java集合框架是一组用来存储和操作数据集合的接口和类。它提供了一种统一的标准方法来操作不同的数据集合&#xff0c;极大简化了编程任务。 集合框架的结构…

我的电脑/资源管理器里无法显示新硬盘?

前情提要 我新&#xff01;买了一个京东京造的SATA3硬盘&#xff0c;一个绿联的SATA3转USB读取 现在我的电脑里只能显示我本地的C盘和D盘&#xff0c;不能显示这个接入的SATA盘。 系统环境&#xff1a;windows11 问题描述 在我的电脑里&#xff0c;只能看到我原本的C和D&…

互联网平台大模型网络架构设计

字节跳动&#xff1a;大模型网络实践分享 自2019年起&#xff0c;字节跳动公司便开始着手白盒项目。2020年&#xff0c;推出了首款接入交换机——25G型号&#xff0c;随后逐步实现软硬件的自主研发。在当前一代产品中&#xff0c;已经实现了100G接入、25.6T400G互联&#xff0c…

扩展——双向搜索

1. 基本概念 单向搜索&#xff1a;传统的搜索算法&#xff08;如广度优先搜索 BFS、深度优先搜索 DFS&#xff09;通常从起点开始&#xff0c;逐步扩展搜索到目标节点。搜索的时间复杂度与图的大小和结构有关。 双向搜索&#xff1a;双向搜索则同时从起点和终点进行搜索&#…

分享8个Python自动化实战脚本!

1. Python自动化实战脚本 1.1 网络自动化 网络上有丰富的信息资源&#xff0c;Python可以帮我们自动化获取这些信息。 爬虫简介&#xff1a;爬虫是一种自动提取网页信息的程序。Python有许多优秀的爬虫库&#xff0c;如requests和BeautifulSoup。 案例&#xff1a;使用Pytho…

软件测试学习笔记丨静态测试与代码审计 SonarQube

本文转自测试人社区&#xff0c;原文链接&#xff1a;https://ceshiren.com/t/topic/32049 一&#xff0c;SonarQube 平台搭建 1.1&#xff0c; 介绍 Sonar 是一个用于代码质量管理的开放平台。通过插件机制&#xff0c;Sonar 可以集成不同的测试工具、代码分析工具&#xff…

Having trouble using OpenAI API

题意&#xff1a;"使用OpenAI API遇到困难" 问题背景&#xff1a; I am having trouble with this code. I want to implement AI using OpenAI API in my React.js project but I cannot seem to get what the issue is. I ask it a question in the search bar in…

大语言模型数据增强与模型蒸馏解决方案

背景 在人工智能和自然语言处理领域&#xff0c;大语言模型通过训练数百亿甚至上千亿参数&#xff0c;实现了出色的文本生成、翻译、总结等任务。然而&#xff0c;这些模型的训练和推理过程需要大量的计算资源&#xff0c;使得它们的实际开发应用成本非常高&#xff1b;其次&a…

线程间数据传递之ThreadLocal、InheritableThreadLocal、TransmittableThreadLocal

线程间数据传递之ThreadLocal、InheritableThreadLocal、TransmittableThreadLocal 1、ThreadLocal介绍 spring 中基于 ThreadLocal 来实现事务。 多线程 访问同一个共享变量的时候容易出现并发问题&#xff0c;ThreadLocal是除了加锁这种同步方式之外的一种保证 规避多线程…

【bug记录7】导入Lottie的json格式动画,获取不到相对路径下的图片

一、问题背景 在vue3项目中&#xff0c;想把Lottie依赖的图片放在其相对路径下&#xff0c;但是发现即使修改其中的u参数&#xff0c;也无法拿到其相对路径中的图片。因为json解析绝对路径&#xff0c;只能将图片放在项目根目录下的public文件夹应急。 二、解决方法 将Lottie…

Lua 代码编码规范

lua代码格式 vscode stylua 插件 配置文件stylua.toml column_width 240 line_endings “Unix” indent_type “Spaces” --使用空格 很重要&#xff0c;保证不同编辑器打开是一样的 indent_width 4 quote_style “AutoPreferDouble” --字符串引号样式双引号 call_paren…

c++关于字符串的练习

提示并输入一个字符串&#xff0c;统计该字符串中字母个数、数字个数、空格个数、其他字符的个数 #include <iostream> #include<string> using namespace std;int main() {string s1;int letter0,digit0,space0,other0;cout<<"请输入一个字符串:"…