Streamlit 项目知识点总结

目录

1. 单选框、下拉框格式化

2. 多媒体资源的引用

2.1 搭建一个简易的http服务器

2.2 约定多媒体资源的输入格式

2.3 解析多媒体资源

3. 设置页面的全局背景图片

4. 输出流式文本(类似打字效果)

4.1 使用内置的 st.write_stream 方法实现

4.2 使用内置的 st.write 方法实现

5. 分页导航

6. 使用模板渲染页面

7. 多页面方案

7.1 创建一个导航文件

7.2 定义每个页面的内容

7.3 渲染导航


        

        最近使用python的streamlit库做了个简单的小项目,过程中碰到了不少问题,现总结如下。

1. 单选框、下拉框格式化

        默认情况下,单选框和下拉框的标签文本就是 options 参数中的列表数据,但在大多数的实际应用场景下,我们不仅需要在页面上显示标签文本,同时还需要传递它们对应的id索引,这个时候,我们就需要对单选框和下拉框的标签进行格式化处理。以下是单选框格式化的示例代码:

# 使用id字段作为索引
option_list = [data.id for data in data_list]
# 使用title字段作为标签文本
label_list = [data.title for data in data_list]
note_id = st.sidebar.radio('', option_list, format_func=lambda item: label_list[option_list.index(item)], label_visibility='collapsed')
if note_id:# 将id参数传递给其他业务逻辑

        提示:该种方式同样适用于下拉框的数据处理。

2. 多媒体资源的引用

        streamlit中有内置的方法可以显示图片、音频和视频等多媒体资源,但请注意,这些方法都是独立的,无法同时输出图片和音视频混合的富文本信息。假如现在有一段文本需要输出,这段文本中不仅包含了文字,同时还包含了图片、音视频等信息,对于这样的场景需求,streamlit中的st.html()方法似乎可以实现,但还不够完美,因为st.html()方法对多媒体资源的引用格式,通常都是http(s)协议的url路径,所以如果能有一个http文件服务器,将streamlit应用中的本地资源,映射成为http资源,那就能完美解决这样的场景需求了。具体实施步骤如下:

2.1 搭建一个简易的http服务器

        基于python的http.server模块,我们可快速搭建一个简易的http服务器。

2.2 约定多媒体资源的输入格式

        在streamlit应用中,约定好多媒体资源的输入格式,示例格式如下:

图片格式:![图片描述][图片地址],图片描述可以为空
音频格式:![audio][音频地址],audio为固定关键词
视频格式:![video][视频地址],video为固定关键词
2.3 解析多媒体资源

        根据约定好的格式,将多媒体资源解析出来,并映射到http文件资源,如下:

import re
import streamlit as stcontent = "我是一段包含了文字、图片和音视频的富文本"# 替换图片,其中st.secrets.httpd.serverUrl是应用中配置的http文件服务器地址
image_pattern = r'!\[(.*)\]\[(.*?)\]'
placeholder = r'<div><img src="{}\2" alt="\1" title="\1" style="max-width: 100%; border-radius: 5px;"/></div>'.format(st.secrets.httpd.serverUrl)
content = re.sub(image_pattern, placeholder, content)# 替换音频
audio_pattern = r'!\[audio\]\[(.*?)\]'
placeholder = r'<div><audio src="{}\1" style="max-width: 100%; border-radius: 5px;" controls>您的浏览器不支持该元素</audio></div>'.format(st.secrets.httpd.serverUrl)
content = re.sub(audio_pattern, placeholder, content)# 替换视频
video_pattern = r'!\[video\]\[(.*?)\]'
placeholder = r'<div><video src="{}\1" style="max-width: 100%; border-radius: 5px;" controls>您的浏览器不支持该元素</video></div>'.format(st.secrets.httpd.serverUrl)
content = re.sub(video_pattern, placeholder, content)# 最后输出
st.html(content)

3. 设置页面的全局背景图片

        背景图片可以是本地文件,也可以是http网络图片,如果是本地图片,必须将它转换为base64字符串,否则无法正常显示。

        核心代码就一条语句,如下:

import streamlit as stst.html(f'''<style>.stApp:before{{background: url({background_image}) no-repeat fixed;background-size: cover;z-index: 1000000;pointer-events: none;position: absolute;width: 100%;height: 100%;content: "";opacity: 0.2;}}</style> 
''')

        其中的background_image是我们需要传递的参数,参数值就是我们前面提到的,要么是http图片路径,要么是图片的base64编码字符串。

        下面附一个图片转base64字符串的方法:

import base64
import streamlit as stimage_path = '本地图片路径'
with open(image_path, 'rb') as file:encoded_string = base64.b64encode(file.read())
data = encoded_string.decode('utf-8')
background_image = 'data:image/png;base64,{}'.format(data)

4. 输出流式文本(类似打字效果)

4.1 使用内置的 st.write_stream 方法实现
import time
import streamlit as st# 将字符串转换为字符生成器
def split_text(string):for char in string:yield chartime.sleep(0.1)# 建议将输出文本放在三个引号内,以保持原有格式
text = '''想和你说,今天的云和你,都十分可爱。\n我把喜欢写进风里,从此整个世界都是你。
'''st.write_stream(split_text(text))
4.2 使用内置的 st.write 方法实现

        st.write 方法更加灵活,可以根据需要定制我们任何想要的输出。先封装一个工具类,如下:

import time
import streamlit as stclass StreamlitUtil():'''将字符串转换为字符生成器@string: 字符串'''@staticmethoddef split_text(string):for char in string:yield chartime.sleep(0.1)'''输出流式字符串(类似打字效果)@obj: 字符串、字符串列表或者字符串生成器@container: 容器对象,默认为st,也可以是其它值,如:st.sidebar等。'''@staticmethoddef write_stream(obj, container=st):if isinstance(obj, str):container.write(StreamlitUtil.split_text(obj))returnif isinstance(obj, list):for item in obj:container.write(StreamlitUtil.split_text(item))returncontainer.write(obj)'''输出流式聊天信息(类似打字效果)@message_list: 聊天信息列表,格式 [{'用户名称1': '内容1'}, {'用户名称2': '内容2'} ...]'''@staticmethoddef write_stream_chat(message_list):for message_dict in message_list:# 注意:popitem()方法会移除最后插入的键值对name, message  = message_dict.popitem()st.chat_message(name).write(StreamlitUtil.split_text(message))

        构造数据并调用:

from streamlit_util import StreamlitUtil as sudef run():text = '想和你说,今天的云和你,都十分可爱。'# 构造字符串列表并以流式输出string_list = []for index in range(3):string_list.append(f'{index+1}: {text}')su.write_stream(string_list)# 构造聊天信息列表并以流式输出string_list = []for index in range(3):string_list.append({'user': f'{index+1}: {text}'})su.write_stream_chat(string_list)run()

5. 分页导航

        分页导航在web应用中是一个非常常见的功能,当有大量数据需要在页面上渲染时,考虑到浏览器页面的承受能力和后台服务器的压力,通常会对数据作分页处理。

        注意:此处只介绍如何实现分页导航的功能,不讨论分页的数据如何获取。

        一个完整的分页导航主要包含两个部分:分页按钮和按钮事件。

        先来看下如何渲染一个分页导航:

'''
显示分页导航栏
@container: 容器对象,即分页导航栏显示在什么地方
@total_page: 总页数
'''
def show_page_nav(container, total_page=1):if total_page < 1:total_page = 1page_nav = {'first_page': '首页','prev_page': '上页','next_page': '下页','last_page': '尾页'}index = 0cols = container.columns(len(page_nav))for key in page_nav:with cols[index]:st.button(page_nav[key], on_click=change_page_state, args=(key, total_page))index += 1current_page = su.get_session('current_page', 1)container.caption('#### 第 {} 页 / 共 {} 页'.format(current_page, total_page))

        show_page_nav 函数中,我们定义了分页导航中包含了哪些按钮,并从session中获取了当前状态是第几页。同时我们还注意到,在定义分页按钮的时候,我们绑定了一个单击事件函数,这个函数的作用就是保存当前状态的页码,它的具体内容如下:

'''
分页按钮的业务逻辑处理,通过session来存储当前页信息
@page_button_name: 分页按钮名称
@total_page: 总页数
'''
def change_page_state(page_button_name, total_page):if page_button_name == 'first_page':su.set_session('current_page', 1)returnif page_button_name == 'prev_page':current_page = su.get_session('current_page', 1)if current_page > 1:su.set_session('current_page', current_page - 1)else:su.set_session('current_page', 1)returnif page_button_name == 'next_page':current_page = su.get_session('current_page', 1)if current_page >= total_page:su.set_session('current_page', total_page)else:su.set_session('current_page', current_page + 1)returnif page_button_name == 'last_page':su.set_session('current_page', total_page)return

        change_page_state 函数中,我们针对每个按钮的单击事件分别进行了处理,处理的最终目的是为了确认当前状态的页码,并将这个页码存储在session中。

        我们发现,以上代码只是渲染了一个分页导航栏,并将按钮点击时的当前页码保存在了session中,似乎并没有关联其它具体的业务逻辑,那么如何将它整合到具体的业务逻辑中呢?其实,关键就在于session,通过session我们可以共享数据,这就意味着,在具体的业务逻辑中,我们只需要将当前页码作为参数传递给获取数据的函数即可。

6. 使用模板渲染页面

        我们知道,streamlit中内置了各种输出函数,可以将我们想要展示的内容渲染到页面上,其中,有一个st.html()函数,为我们渲染丰富多彩的页面提供了无限可能。

        试想下,如果要渲染一段样式丰富的文本,我们会怎么做呢?最容易想到的就是直接在python代码中定义好样式和内容,并将他们通过st.html()函数进行输出。这样做,从功能实现上来说没问题,但由于我们将样式和内容混在了一起,尤其当样式很多的时候,对于代码的后期维护将会是一个灾难。这个时候,你可能就会想,那如果将样式和内容分离呢?好注意,那么就让我们来看下,如何实现样式和内容的分离。

        首先,定义一个html文件模板,示例内容如下:

<div style="text-align: center;"><div style="font-weight: bold;">{title}</div><div style="color: #999999;">{publish_time}</div>
</div>
<div style="margin-top: 10px;">{content}
</div>

        我们看到,模板文件中,除了html标签和样式,我们还定义了几个变量,这些变量用花括号引起来,我们姑且称它们为占位符。

        下面,我们再来看下如何引用这个模板,并使用其中的占位符:

# 定义模板文件路径
template = 'page/template/content.html'
# 读取模板文件内容,并替换其中的占位符变量
with open(template, 'r') as file:content = file.read()content = content.replace('{title}', '厉害了我的国')content = content.replace('{publish_time}', '2024-05-31')content = content.replace('{content}', '这里是一大段内容...')# 输出内容到页面st.html(content)

        怎么样?这样的代码看起来是不是很清爽干净,后期的维护也会简单轻松很多。

7. 多页面方案

        从1.36.0版本开始,streamlit 启用了新的多页面方案,使用起来更加简单、灵活。

        导航的定义建议使用字典格式,如下:

pages = {'一级导航1' : [st.Page('py文件路径', title='📘 二级导航1', url_path='url路径,用于显示在地址栏中', default=True),st.Page('py文件路径', title='📋️ 二级导航2', url_path='url路径,用于显示在地址栏中', default=False)],'一级导航2' : [st.Page('py文件路径', title='🃏 二级导航3', url_path='url路径,用于显示在地址栏中', default=False),st.Page('py文件路径', title='🎁 二级导航4', url_path='url路径,用于显示在地址栏中', default=False)]
}

        属性说明:

        第一个参数:导航页面对应的py文件路径,建议使用相对路径。

        title:二级导航的名称。

        url_path:导航的url路径,用于显示在浏览器的地址栏中,如果未定义该参数,则默认使用py文件名称(去除.py后缀)作为url路径。

        default:是否作为应用的默认页面,默认为 False,默认情况下,取 st.navigation 方法参数中的第一个页面作为应用的首页。

        下面来演示一个简单的多页面应用。

7.1 创建一个导航文件

        创建一个 router.py 文件,项目中所有的导航页面都存放在这个文件中,内容如下:

import streamlit as stdef load_router():pages = {'🏠️ 导航名称1' : [st.Page('pages/front/测试1.py', title='📘 子导航1'),st.Page('pages/front/测试2.py', title='📋️ 子导航2')],'⚙️ 导航名称2' : [st.Page('pages/admin/测试3.py', title='🃏 子导航3'),st.Page('pages/admin/测试4.py', title='🎁 子导航4')]}return pages
7.2 定义每个页面的内容

        以 测试1.py 文件为例,它的内容如下:

import streamlit as stdef run():st.write('欲买桂花同载酒')run()
7.3 渲染导航
import streamlit as st
import router as navdef run():st.set_page_config(layout='wide', page_title='导航示例')pg = st.navigation(nav.load_router())pg.run()run()

        效果如下:

         如有疑问,可以关注 我的知识库,直接提问即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/pingmian/82455.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

maven模块化开发

使用方法 将项目安装到本地仓库 mvn install 的作用 运行 mvn install 时&#xff0c;Maven 会执行项目的整个构建生命周期&#xff08;包括 compile、test、package 等阶段&#xff09;&#xff0c;最终将构建的 artifact 安装到本地仓库&#xff08;默认路径为 ~/.m2/repos…

(11)Service Mesh架构下Java应用实现零信任安全模型

Service Mesh架构下Java应用实现零信任安全模型 📌 TL;DR: 本文详细介绍如何在Service Mesh架构中实现零信任安全模型,包括身份认证、授权控制、加密通信和持续监控四大核心技术,以及与Istio、Envoy等组件的集成方案。 目录 零信任安全模型概述关键技术实现最佳实践Service…

修改 K8S Service 资源类型 NodePort 的端口范围

在 Kubernetes 中&#xff0c;Service 类型为 NodePort 时&#xff0c;默认分配的端口范围为 30000~32767。如果你希望使用自定义端口&#xff08;如 8080、8888 等&#xff09;&#xff0c;就需要修改 kube-apiserver 的默认配置。 本文将详细介绍如何修改 Kubernetes 中 Nod…

MySQL 可观测性最佳实践

MySQL 简介 MySQL 是一个广泛使用的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;以其高性能、可靠性和易用性而闻名&#xff0c;适用于各种规模的应用&#xff0c;从小型网站到大型企业级系统。 监控 MySQL 指标是维护数据库健康、优化性能和确保数据…

CentOS安装最新Elasticsearch8支持向量数据库

大家都知道Elasticsearch是支持向量的存储和查询的&#xff0c;今天我们来介绍下如何安装支持向量数据库的Elasticsearch &#xff0c; 操作环境是CentOS。 成功安装截图 大家进入系统shell&#xff0c;跟我执行下面命令进行安装。 更新系统 [rootlocalhost ~]# sudo yum u…

SDL2常用函数SDL事件处理:SDL_Event|SDL_PollEvent

SDL_Event SDL_Event是个联合体&#xff0c;是SDL中所有事件处理的核心。 SDL_Event是SDL中使用的所有事件结构的并集。 只要知道了那个事件类型对应SDL_Event结构的那个成员&#xff0c;使用它是一个简单的事情。 下表罗列了所有SDL_Event的所有成员和对应类型。 Uint32typ…

webpack吐环境分析

需要解决的问题 扣取下来的webpack文件过大 解决思路 用ast将需要的代码扣下来 结果展示 实现步骤 第一步&#xff1a;我们得知道需要哪些模块 在入口处&#xff0c;增加模块记录 第二步&#xff0c;分析ast代码 通过分析发现,key 有三种值 分别为NumbericLiteral、StringLi…

微软语音合成助手资源下载

微软语音合成助手资源下载 【下载地址】微软语音合成助手资源下载 微软语音合成助手是一款基于先进AI技术的文本转语音工具&#xff0c;能够将文字内容快速转换为自然流畅的语音。它支持高度自定义的语音参数&#xff0c;包括语速、音调、发音和停顿等&#xff0c;满足多样化需…

青少年编程与数学 02-020 C#程序设计基础 01课题、C#编程概要

青少年编程与数学 02-020 C#程序设计基础 01课题、C#编程概要 一、微软.NET开发平台1. 核心组件2. 特点3. 应用场景4. 开源与社区5. 版本与更新6. 学习资源 二、C# 编程语言1. 历史背景2. 语言特性&#xff08;1&#xff09;面向对象&#xff08;2&#xff09;类型安全&#xf…

图片文件未正确加载​—— Webpack 无法正确解析图片,生成了一个空的 Base64 URL

如果你打印出的图片 URL 是 data:image/png;base64, 后面没有实际的 Base64 数据&#xff0c;可能有以下几种原因&#xff1a; ​​1. 图片文件未正确加载​​ ​​可能原因​​&#xff1a;图片路径错误&#xff0c;导致 Webpack 无法正确解析图片&#xff0c;生成了一个空的…

3D打印仿造+ AI大脑赋能,造出会思考的全景相机

在自然界的生存竞赛里&#xff0c;节肢动物堪称视觉界的 "卷王"&#xff01;那些长着复眼的小机灵鬼&#xff0c;比如蜜蜂、蜻蜓&#xff0c;别看个头小&#xff0c;视觉能力却超强。 现在&#xff0c;科学家把它们的眼睛 " 偷"过来啦 —— 不是真偷&…

rabbitmq单机多实例部署

RabbitMQ 单实例部署 单实例部署是指在一台服务器上运行一个 RabbitMQ 实例。这种部署方式适用于小型应用或开发环境,配置简单,资源占用较少。单实例部署的核心是安装 RabbitMQ 并启动服务,通常需要配置 Erlang 环境,因为 RabbitMQ 是基于 Erlang 编写的。单实例部署的优势…

知识宇宙-职业篇:后端工程师

名人说&#xff1a;博观而约取&#xff0c;厚积而薄发。——苏轼《稼说送张琥》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、后端工程师的定义与职责1. 什么是后端工程师&#xff1f;2. 主要工作职责 二、…

机试 | vector/array Minimum Glutton C++

题目地址 &#xff1a; C - Minimum Glutton #include<stdio.h> #include<iostream> #include<vector> #include<algorithm> using namespace std; int main() {//N:菜肴数&#xff0c;X&#xff1a;总甜度阈值&#xff0c;Y&#xff1a;总咸度阈值int…

【Django ORM】三万字了解Django ORM的基本概念和基本使用

第一章 Django ORM 概述 1.1 什么是Django ORM 1.1.1 ORM的基本概念 ORM 即对象关系映射&#xff08;Object Relational Mapping&#xff09;&#xff0c;它是一种编程技术&#xff0c;用于在面向对象编程语言&#xff08;如 Python&#xff09;和关系型数据库&#xff08;如…

在springboot项目中是否可以使用两个不同地址的redis

在Spring Boot项目中可以通过多数据源配置的方式使用两个不同地址的Redis实例。以下是具体实现方案 1.依赖配置 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusio…

JMeter 教程:监控性能指标 - 第三方插件安装(PerfMon)

目录 【简单介绍】 ✅ PerfMon 插件是什么&#xff1f; &#x1f6e0;️ 安装 PerfMon 插件 方法一&#xff1a;使用 JMeterPluginsManager 安装&#xff08;推荐&#xff09; &#x1f50c; 安装完成后组件介绍 &#x1f310; 服务端安装 ServerAgent&#xff08;用于被…

【后端高阶面经:数据库篇】19、分库分表查询困境:无分库分表键时的高效应对

一、分库分表下的无分片键查询困境 在分布式数据库架构中,分库分表通过分片键(如买家ID)将数据分散存储,显著提升了单表性能和系统扩展性。然而,当业务需要从非分片键维度(如卖家ID)进行查询时,传统架构暴露出以下核心问题: 1.1 跨分片扫描的性能灾难 数据分散性:以…

ARM架构

目录 哈佛结构 arm指令格式 有符号数的溢出&#xff08;8bit)​ 无符号数的进位/借位 CPSR&#xff08;当前程序状态寄存器&#xff09; ARM模式 arm异常类型 ARMv7架构异常向量表 arm异常的处理流程 arm寄存器 堆栈指针寄存器 arm模式切换流程 LDR指令、STR指令 指…

canvas(三)-动画3d

在 <canvas> 中实现 3D 动画通常需要借助 WebGL 技术,因为原生的 2D 上下文(CanvasRenderingContext2D)无法直接支持 3D 渲染。WebGL 是基于 OpenGL ES 2.0 的 JavaScript API,可以直接在浏览器中实现高性能的 3D 图形渲染。以下是关于 <canvas> 3D 动画的概念…