Streamlit 是一个开源的 Python 框架,旨在让数据科学家和机器学习工程师能够快速、轻松地创建交互式 Web 应用程序,而无需深厚的前端开发背景。本文代码允许基于树莓派 ubuntu 24.04TLS,python 版本,3.12.11

Streamlit 内容参考:官方文档

# 安装 Streamlit

# 激活 conda 环境

使用 conda 创建虚拟环境,激活环境后,在其中安装 Streamlit ,相关操作不再赘述,可参考 ubuntu 安装 conda 的文章内容。

# 安装 Streamlit 库

使用 pip 安装: pip install streamlit

在 vscode 中远程 ubuntu 并下载 streamlit

(base) root@Umadeus:/opt/pythonProject/streamlit# conda activate pyweb
(pyweb) root@Umadeus:/opt/pythonProject/streamlit# pip install streamlit

# 启动示例 Streamlit 应用

通过 streamlit hello 启用一个 streamlit 示例应用:

(pyweb) root@Umadeus:/opt/pythonProject/streamlit# streamlit hello
Collecting usage statistics. To deactivate, set browser.gatherUsageStats to false.
  Welcome to Streamlit. Check out our demo in your browser.
  Local URL: http://localhost:8501
  Network URL: http://192.168.8.15:8501
  External URL: http://223.160.116.13:8501

# 运行 Streamlit

要使用 Streamlit 运行 Python 脚本,只需要输入 : streamlit run

streamlit run your_script.py [-- script args]

运行上述命令,本地 Streamlit 服务器就会启动,应用程序将在默认网络浏览器的新选项卡中打开。可以在应用程序其中绘制图表、文本、小部件、表格等。

运行后, Streamlit 默认使用 8501 端口,如果你想更改端口,可以使用: streamlit run your_script.py ----server.port 8080

注意:传递脚本时,必须在两个破折号之后传递一些自定义参数。否则, 参数被解释为 Streamlit 本身的参数。

# 基本概念

# 基础概念

# 运行 Streamlit

运行 Streamlit 有两种方法:使用 Streamlit run 或者是 python 模块

# Running
python -m streamlit run your_script.py
# is equivalent to:
streamlit run your_script.py

您还可以将 URL 传递给 streamlit run : streamlit run https://raw.githubusercontent.com/streamlit/demo-uber-nyc-pickups/master/streamlit_app.py

# 开发流程

每次想要更新应用时,请保存源文件。当您这样做时,Streamlit 会检测文件是否有变化,并询问您是否愿意 重新运行您的应用程序。选择屏幕右上角的 “始终重新运行” 以 每次更改源代码时,都会自动更新您的应用。

这允许您在快速交互循环中工作:您输入一些代码,保存 它,实时试用,然后输入更多代码,保存它,试用它,依此类推 直到您对结果感到满意为止。编码和查看之间的紧密循环 实时结果是 Streamlit 让您的生活更轻松的方式之一。

从 Streamlit 1.10.0 及更高版本开始,Streamlit 应用程序无法从 Linux 发行版的根目录运行。如果你尝试从根目录运行 Streamlit 应用程序,Streamlit 会抛出一个错误。有关详细信息,请参阅 GitHub 问题 #5239。FileNotFoundError: [Errno 2] No such file or directory

如果你使用的是 Streamlit 1.10.0 或更高版本,你的主脚本应该位于根目录以外的目录中。使用 Docker 时,您可以使用该命令指定主脚本所在的目录。有关如何执行此作的示例,请阅读 创建 Dockerfile

# 数据流

Streamlit 的架构允许您像编写普通应用程序一样编写应用程序 Python 脚本。为了解锁这一点,Streamlit 应用程序有一个独特的数据流:当必须在屏幕上更新某些内容时,Streamlit 会从上到下重新运行您的整个 Python 脚本。

这可能发生在两种情况下:

  • 每当您修改应用的源代码时。
  • 每当用户与应用程序中的小部件交互时。例如,当拖动 滑块、在输入框中输入文本或单击按钮。

每当通过 on_change (或 on_click )参数将回调传递给小部件时,回调总是会在脚本的其余部分之前运行。有关回调 API 的详细信息,请参阅我们的 会话状态 API 参考指南

为了使这一切快速无缝,Streamlit 在幕后为您做了一些繁重的工作。这个工作中的一个重要角色是 @st.ache_data 装饰器,它允许开发人员在重新运行应用程序时跳过某些昂贵的计算。我们将在本页稍后介绍缓存。

# 显示和设置数据样式

有几种方法可以在 Streamlit 中显示数据(表、数组、data frames) 下面将介绍 魔术方法 和 st.write() ,它们可用于编写 从文本到表格的任何内容。

# 使用魔法函数

您还可以在不调用任何 Streamlit 方法的情况下写入您的应用程序。Streamlit 支持 magic commands,这意味着你可以无需要使用 st.write () ,参考如下例子:

import streamlit as st
import pandas as pd
df = pd.DataFrame ({
    "Column 1": [1, 2, 3],
    "Column 2": [4, 5, 6],
    "Column 3": [7, 8, 9]
})
df

每当 Streamlit 在自己的行上看到变量或文字值时,它都会使用 st.write () 自动将其写入您的应用程序。上述代码使用 streamlit run 运行后,会直接在 web 上显示一个表格

# 写入 data frame

与魔术命令一样,st.write()是 Streamlit 的核心方法。您几乎可以将任何内容传递给 st.write():文本、数据、Matplotlib 图形、Altair 图表等等。别担心,Streamlit 会解决这个问题,并以正确的方式渲染。

import streamlit as st
import pandas as pd
st.write ("Here's our first attempt at using data to create a table:")
st.write (pd.DataFrame ({
    "Column 1": [1, 2, 3],
    "Column 2": [4, 5, 6],
    "Column 3": [7, 8, 9]
}))

还有其他特定于数据的函数,如 st.dataframe ()st.table () ,您也可以使用它们来显示数据。让我们了解一下何时使用这些功能,以及如何为数据帧添加颜色和样式。

你可能会问为什么我不总是使用 st.write()?有几个原因:

  1. Magic 和 st.write () 检查您传入的数据类型,然后决定如何在应用程序中最好地呈现它。有时你想用另一种方式来画。例如,您可能希望使用 st.table(df) 将数据框绘制为静态表,而不是将其绘制为交互式表。

  2. 其他方法返回一个可以使用和修改的对象,可以通过向其添加数据或替换数据来实现。

  3. 如果您使用更具体的 Streamlit 方法,则可以传递其他参数来自定义其行为。

例如,让我们创建一个 data frame ,并使用 Pandas Styler 对象更改其格式。在这个例子中,您将使用 Numpy 生成一个随机样本,并使用 st.dataframe () 方法绘制一个交互式表(此示例使用 Numpy 生成随机样本,但您可以使用 Pandas DataFrames、Numpy 数组或纯 Python 数组)

import streamlit as st
import numpy as np
# 生成一个 10×20 的随机数矩阵
dataframe = np.random.randn (10, 20)
st.dataframe (dataframe)

让我们扩展上述示例,使用 Pandas 对象来突出显示 交互式表格中的某些元素:

import streamlit as st
import numpy as np
import pandas as pd
# 生成 10 行 20 列的 DataFrame
dataframe = pd.DataFrame (
    np.random.randn (10, 20),
    # 为每一列创建名称
    columns=('col % d' % i for i in range (20)))
# 对数据框应用样式,高亮显示每列的最大值
st.dataframe (dataframe.style.highlight_max (axis=0))

Streamlit 还有一个静态表生成方法:st.table ()

import streamlit as st
import numpy as np
import pandas as pd
dataframe = pd.DataFrame (
    np.random.randn (10, 20),
    columns=('col % d' % i for i in range (20)))
st.table (dataframe)

# 绘制图表

Streamlit 支持几个流行的数据图表库,如 Matplotlib、 Altair、deck.gl 等。具体参考对应章节。

# 绘制折线图

您可以使用 st.line_chart () 轻松地将折线图添加到您的应用程序中。我们将生成一个随机的 使用 Numpy 进行采样,然后绘制图表。

# 绘制地图

使用 st.map (),您可以在地图上显示数据点。 让我们使用 Numpy 在武汉市中心生成 10 个随机点。

import streamlit as st
import numpy as np
import pandas as pd
map_data = pd.DataFrame (
    np.random.randn (10, 2) / [50, 50] + [30.5928, 114.3055],
    columns=['lat', 'lon'])
st.map (map_data)

np.random.randn (10, 2) / [50, 50] + [30.5928, 114.3055]

  • np.random.randn (10, 2) : 生成 10 行 2 列的标准正态分布随机数矩阵
  • / [50, 50] : 将随机数除以 50,缩小分布范围(约 0.02 度范围内)
  • + [30.5928, 114.3055] : 将武汉市中心坐标作为基准点添加到随机偏移量上

# 控件(Widgets)

当你将数据或模型置于想要交互的状态时,你可以添加像 s.slider()st.button()st.selectbox() 这样的小部件,你可以将小部件视为变量

# slider

在第一次运行时,下方示例的应用程序应该输出文本 “0 平方为 0”。然后,每次用户与小部件交互时,Streamlit 都会从上到下重新运行您的脚本,将小部件的当前状态分配给过程中的变量。

例如,如果用户将滑块移动到位置 10,Streamlit 将重新运行下述代码,并相应地将 x 设置为 10。所以现在你应该看到文本 “10 平方是 100”。

import streamlit as st
x = st.slider ('x')  # 👈 this is a widget
st.write (x, 'squared is', x * x)

# text_input

如果您选择指定一个字符串作为小部件的唯一键,则也可以通过键访问小部件:

import streamlit as st
st.text_input ("Your name", key="name")
# 在任何时候通过以下方式访问该值
st.session_state.name

st.session_state.name

  • st.session_state 是 Streamlit 的会话状态对象,用于在用户与应用交互时保存数据。
  • .name 对应于文本输入框的 key="name" 参数
  • 当用户在文本输入框中输入内容时,值会自动保存到 st.session_state.name
  • 在同一个用户会话中,你也可以在代码的任何地方读取这个值,即使页面重新运行。

每个带有键的小部件都会自动添加到会话状态中。有关会话状态、其与小部件状态的关联及其限制的更多信息,请参阅 会话状态 API 参考指南

# checkboxes

复选框的一个用例是隐藏或显示应用程序中的特定图表或部分。(st.checkbox ())[https://docs.streamlit.io/develop/api-reference/widgets/st.checkbox] 接受一个参数,即小部件标签。在此示例中,复选框用于切换条件语句。

import streamlit as st
import numpy as np
import pandas as pd
if st.checkbox ('Show dataframe'):
    chart_data = pd.DataFrame (
       np.random.randn (20, 3),
       columns=['a', 'b', 'c'])
    chart_data

# selectbox

使 st.select () 框从系列中选择。您可以写入所需的选项,也可以传递数组或 data frame 列

import streamlit as st
import pandas as pd
df = pd.DataFrame ({
    'first column': [1, 2, 3, 4],
    'second column': [10, 20, 30, 40]
    })
option = st.selectbox (
    'Which number do you like best?',
     df ['first column'])
'You selected: ', option

# 布局(Layout)

Streamlit 使您可以使用 st.sidebar 在左侧面板侧边栏中轻松组织小部件。传递给 st.sidebar 的每个元素都固定在左侧,允许用户专注于应用程序中的内容,同时仍然可以访问 UI 控件。

例如,如果你想在侧边栏中添加一个选择框和一个滑块,请使用 st.sidebar.sliderst.sidebar.selectbox ,而不是 st.sliderst.selectbox

import streamlit as st
# Add a selectbox to the sidebar:
add_selectbox = st.sidebar.selectbox (
    'How would you like to be contacted?',
    ('Email', 'Home phone', 'Mobile phone')
)
# Add a slider to the sidebar:
add_slider = st.sidebar.slider (
    'Select a range of values',
    0.0, 100.0, (25.0, 75.0)
)

除了侧边栏,Streamlit 还提供了其他几种控制应用程序布局的方法。st.columns 允许您并排放置小部件,st.expander 允许您通过隐藏大型内容来节省空间。

import streamlit as st
left_column, right_column = st.columns (2)
# You can use a column just like st.sidebar:
left_column.button ('Press me!')
# Or even better, call Streamlit functions inside a "with" block:
with right_column:
    chosen = st.radio (
        'Sorting hat',
        ("Gryffindor", "Ravenclaw", "Hufflepuff", "Slytherin"))
    st.write (f"You are in {chosen} house!")

当前版本,st.echo 在侧边栏或布局选项中不受支持。

# 显示进度

当向应用程序添加长时间运行的计算时,您可以使用 st.progress () 实时显示状态。

import streamlit as st
import time
'Starting a long computation...'
# Add a placeholder
latest_iteration = st.empty ()
bar = st.progress (0)
for i in range (100):
  # Update the progress bar with each iteration.
  latest_iteration.text (f'Iteration {i+1}')
  bar.progress (i + 1)
  time.sleep (0.1)
'...and now we\'re done!'

# 高级概念

现在你知道 Streamlit 应用程序是如何运行和处理数据的,让我们来谈谈效率。缓存(Caching )允许您保存函数的输出,以便在重新运行时跳过它。会话状态(Session State)允许您保存在重新运行之间保留的每个用户的信息。这不仅可以避免不必要的重新计算,还可以创建动态页面并处理渐进过程。

# 缓存(Caching)

Caching 使您的应用程序即使在从 web 加载数据、操纵大型数据集或执行昂贵的计算时也能保持高性能。

缓存背后的基本思想是存储昂贵函数调用的结果,并在再次出现相同的输入时返回缓存的结果。这避免了重复执行具有相同输入值的函数。

要在 Streamlit 中缓存一个函数,您需要对其应用缓存装饰器。您有两个选择:

st.cache_data 是缓存返回数据的计算的推荐方法。当您使用返回可序列化数据对象(例如 str、int、float、DataFrame、dict、list)的函数时,请使用 st.ache_data 。它在每次函数调用时都会创建一个新的数据副本,使其免受突变和竞争条件的影响。在大多数情况下,st.ache_data 的行为是你想要的 —— 所以如果你不确定,可以从 st.ache_dada 开始,看看它是否有效!

st.cache_resource 是缓存全局资源(如 ML 模型或数据库连接)的推荐方式。当您的函数返回不希望多次加载的不可序列化对象时,请使用 st.ache_resource 。它返回缓存对象本身,该对象在所有重新运行和会话中共享,而无需复制或重复。如果使用 st.ache_resource 对缓存的对象进行变异,则该变异将存在于所有重新运行和会话中。

@st.cache_data
def long_running_function (param1, param2):
    return

在上面的例子中, long_running_function@st.ache_data 修饰。因此, Streamlit 注意到以下几点:

  • 函数的名称(“long_running_function”)。
  • 输入值(param1、param2)。
  • 函数内的代码。

long_running_function 中运行代码之前, Streamlit 会检查其缓存中是否有以前保存的结果。如果它找到给定函数和输入值的缓存结果,它将返回该缓存结果,而不会重新运行函数的代码。否则,Streamlit 将执行该函数,将结果保存在缓存中,并继续运行脚本。在开发过程中,缓存会随着功能代码的更改而自动更新,确保最新的更改反映在缓存中。

# 会话状态(Session State)

Session State 提供了一个类似字典的界面,您可以在其中保存在脚本重新运行之间保留的信息。使用带有键或属性符号的 st.session_state 来存储和调用值。例如, st.session_state ["my_key"]st.session_state.my_key 。记住,小部件可以自己处理它们的状态,所以你并不总是需要使用会话状态!

# 什么是会话?

会话是查看应用程序的单个实例。如果您从浏览器中的两个不同选项卡查看应用程序,则每个选项卡都有自己的会话。因此,应用程序的每个查看器都将有一个与他们的特定视图绑定的会话状态。Streamlit 在用户与应用程序交互时维护此会话。如果用户刷新浏览器页面或重新加载应用程序的 URL,他们的会话状态将重置,并重新开始新的会话。

# 使用会话状态的示例

这是一个简单的应用程序,可以计算页面运行的次数。每次单击按钮时,脚本都会重新运行。

import streamlit as st
if "counter" not in st.session_state:
    st.session_state.counter = 0
st.session_state.counter += 1
st.header (f"This page has run {st.session_state.counter} times.")
st.button ("Run it again")
  1. 首次运行:应用程序首次为每个用户运行时,会话状态为空。因此,创建了一个键值对(“计数器”:0)。随着脚本的继续,计数器立即递增(“计数器”:1),结果显示:“此页面已运行 1 次。” 当页面完全呈现时,脚本已完成,Streamlit 服务器等待用户执行操作。当该用户单击按钮时,重新运行开始。

  2. 第二次运行:由于 “counter” 已经是会话状态中的一个键,因此不会重新初始化。随着脚本的继续,计数器递增(“计数器”:2),结果显示:“此页面已运行 2 次。”

在一些常见的场景中,会话状态是很有用的。如上所示,当您有一个从一次重新运行到下一次的渐进过程时,会使用会话状态。会话状态也可用于防止重新计算,类似于缓存。然而,这些差异很重要:

  • 缓存将存储的值与特定的函数和输入相关联。所有会话中的所有用户都可以访问缓存值。
  • 会话状态将存储的值与键(字符串)相关联。会话状态中的值仅在保存它的单个会话中可用。

如果你的应用程序中有随机数生成,你可能会使用会话状态。这是一个在每个会话开始时随机生成数据的示例。通过将此随机信息保存在会话状态中,每个用户在打开应用程序时都会获得不同的随机数据,但在与应用程序交互时,这些数据不会不断变化。如果您使用选择器选择不同的颜色,您将看到数据不会在每次重新运行时重新随机化。(如果您在新选项卡中打开应用程序以开始新会话,您将看到不同的数据!)

import streamlit as st
import pandas as pd
import numpy as np
if "df" not in st.session_state:
    st.session_state.df = pd.DataFrame (np.random.randn (20, 2), columns=["x", "y"])
st.header ("Choose a datapoint color")
color = st.color_picker ("Color", "#FF0000")
st.divider ()
st.scatter_chart (st.session_state.df, x="x", y="y", color=color)

如果你为所有用户提取相同的数据,你可能会缓存一个检索该数据的函数。另一方面,如果您提取特定于用户的数据,例如查询他们的个人信息,您可能希望将其保存在会话状态中。这样,查询的数据仅在该会话中可用。
如基本概念中所述,会话状态也与小部件有关。小部件很神奇,可以自己安静地处理状态。然而,作为一项高级功能,您可以通过为小部件分配键来操纵代码中小部件的值。分配给小部件的任何键都将成为会话状态中与小部件值绑定的键。这可用于操纵小部件。

# 连接(Connections)

您可以使用 @st.ache_resource 缓存连接。这是最通用的解决方案,它允许您使用任何 Python 库中的几乎任何连接。然而,Streamlit 还提供了一种方便的方法来处理一些最流行的连接,比如 SQL!st.connection 会为您处理缓存,这样您就可以享受更少的代码行。从数据库中获取数据可以像以下操作一样简单:

import streamlit as st
conn = st.connection ("my_database")
df = conn.query ("select * from my_table")
st.dataframe (df)

当然,您可能想知道您的用户名和密码在哪里。Streamlit 有一个方便的秘密管理机制。现在,让我们看看 st.connection 是如何很好地处理密钥的。在本地项目目录中,可以创建 .streamlit/secrets.toml 文件。将密钥保存在 toml 文件中, st.connection 会使用它们!例如,如果你有一个应用程序文件 streamlit_app.py ,你的项目目录可能看起来像这样:

your-LOCAL-repository/
├── .streamlit/
│   └── secrets.toml # Make sure to gitignore this!
└── streamlit_app.py

对于上面的 SQL 示例,secrets.toml 文件可能如下所示:

[connections.my_database]
    type="sql"
    dialect="mysql"
    username="xxx"
    password="xxx"
    host="example.com" # IP or URL
    port=3306 # Port number
    database="mydb" # Database name

# 附加功能

# 主题

Streamlit 支持开箱即用的浅色和深色主题。Streamlit 将首先检查查看应用程序的用户的操作系统和浏览器是否设置了亮模式或暗模式偏好。如果是这样,那么将使用该偏好。否则,默认情况下将应用灯光主题。

您还可以从 “⋮”→“设置” 更改活动主题。

# 页面

随着内容的增长,你或许需要组织多个页面。Streamlit 提供了一种使用 st.Pagest.navigation 创建多页应用程序的强大方法。只需创建页面并将其与导航连接,如下所示:

  1. 创建一个定义和连接页面的入口点脚本
  2. 为每个页面的内容创建单独的 Python 文件
  3. 使用 st.Page 定义页面,使用 st.navigation 连接页面

以下是一个三页应用程序的示例:

streamlit_app.py

import streamlit as st
# Define the pages
main_page = st.Page ("main_page.py", title="Main Page", icon="🎈")
page_2 = st.Page ("page_2.py", title="Page 2", icon="❄️")
page_3 = st.Page ("page_3.py", title="Page 3", icon="🎉")
# Set up navigation
pg = st.navigation ([main_page, page_2, page_3])
# Run the selected page
pg.run ()

main_page.py

import streamlit as st
# Main page content
st.markdown ("# Main page 🎈")
st.sidebar.markdown ("# Main page 🎈")

page_2.py

import streamlit as st
st.markdown ("# Page 2 ❄️")
st.sidebar.markdown ("# Page 2 ❄️")

page_3.py

import streamlit as st
st.markdown ("# Page 3 🎉")
st.sidebar.markdown ("# Page 3 🎉")

现在运行 streamlit run streamlit_app.py ,导航菜单将自动出现,允许用户在页面之间切换。

阅读更多关于 多页应用程序的文档 教您如何向应用程序添加页面,包括如何定义页面、构建和运行多页应用以及在页面之间导航。

# 自定义组件

如果你在 Streamlit 库中找不到合适的组件,请尝试自定义组件来扩展 Streamlit 的内置功能。在 组件 库中浏览和浏览社区创建的热门组件。如果你涉足前端开发,你可以使用 Streamlit 的 组件 API 构建自己的自定义组件。

# 静态文件服务

Streamlit 运行一个客户端连接的服务器。这意味着您的应用程序的观众无法直接访问您的应用程序本地的文件。大多数时候,这并不重要,因为 Streamlt 命令会为您处理这个问题。当您使用 st.image(<path-to-image>) 时,Streamlit 服务器将访问该文件并处理必要的托管,以便您的应用程序查看器可以看到它。但是,如果您想要一个指向图像或文件的直接 URL,则需要托管它。这需要设置正确的配置,并将托管文件放置在名为 static 的目录中。例如,您的项目可能看起来像:

your-project/
├── static/
│   └── my_hosted-image.png
└── streamlit_app.py

如需了解详情,请阅读我们的 静态文件设置指南

# 应用测试

Streamlit 有一个内置的测试框架,可以让你轻松构建测试。使用您最喜欢的测试框架运行测试,例如 pytest。当你测试 Streamlit 应用程序时,你模拟运行应用程序,声明用户输入,并检查结果。您可以使用 GitHub 工作流来自动化您的测试,并获得有关中断更改的即时警报。在我们的 应用程序测试指南 中了解更多信息。

# API 参考

# 写作与魔法

# st.write

st.write 在应用程序中显示参数,与其他 Streamlit 不同 命令,st.write() 有一些独特的属性:

  • 您可以传入多个参数,所有这些参数都将显示出来。
  • 其行为取决于输入类型。

# 函数签名

st.write (*args, unsafe_allow_html=False)

参数名类型描述
*args任意在应用中显示的一个或多个对象,具体处理逻辑见下表
unsafe_allow_html布尔值是否渲染 *args 中的 HTML(仅适用于字符串或 _repr_html_() 对象)。
・默认 False :转义 HTML 标签视为纯文本 <br>・ True :直接渲染 HTML 表达式 <br>** 注意 **:自定义 HTML 会影响安全性、样式和可维护性 < br>> ** 提示 **:纯 HTML/CSS 插入建议改用 st.html ()

# 参数: *args

输入类型处理方式
str使用 st.markdown ()
dataframe-like、 dictlist使用 st.dataframe ()
异常对象使用 st.exception ()
函数 / 模块 / 类使用 st.help ()
DeltaGenerator使用 st.help ()
Altair 图表使用 st.altair_chart ()
Bokeh 图形使用 st.bokeh_chart ()
Graphviz 图使用 st.graphviz_chart ()
Keras 模型转换后使用 st.graphviz_chart ()
Matplotlib 图形使用 st.pyplot ()
Plotly 图形使用 st.plotly_chart ()
PIL.Image使用 st.image ()
生成器或流(如 openai.Stream)使用 st.write_stream ()
SymPy 表达式使用 st.latex ()
实现 ._repr_html_() 的对象使用 st.html ()
Database cursor以表格形式显示 DB API 2.0 cursor 结果
Anystr (arg) 显示为内联代码

# 参数: unsafe_allow_html

布尔类型参数,默认为 false。

该参数表示是否在 * args 内呈现 HTML。这仅适用于落在_repr_HTML_()上的字符串或对象。若此值为 False(默认值),则正文中发现的任何 HTML 标签都将被转义,因此被视为原始文本。若此为 True,则正文中的任何 HTML 表达式都将被呈现。
向应用程序添加自定义 HTML 会影响安全性、样式和可维护性,如果您只想插入 HTML 或 CSS 而没有 Markdown 文本, 建议改用 st.html

# returns

None

# 示例

它的基本用例是绘制 Markdown 格式的文本,只要 input 是一个字符串:

import streamlit as st
st.write ("Hello, *World!* :sunglasses:")

st.write() 还接受其他数据格式,例如 数字、数据框、样式数据框和各种对象:

import streamlit as st
import pandas as pd
st.write (1234)
st.write (
    pd.DataFrame (
        {
            "first column": [1, 2, 3, 4],
            "second column": [10, 20, 30, 40],
        }
    )
)

您可以同时传入多个参数:

import streamlit as st
st.write ("1 + 1 =", 2)
st.write ("Below is a DataFrame:", data_frame, "Above is a dataframe.")

st.write 也接受图表对象,例如:

import streamlit as st
import pandas as pd
import numpy as np
import altair as alt
df = pd.DataFrame (np.random.randn (200, 3), columns=["a", "b", "c"])
c = (
    alt.Chart (df)
    .mark_circle ()
    .encode (x="a", y="b", size="c", color="c", tooltip=["a", "b", "c"])
)
st.write (c)

# st.write_stream

将生成器、可迭代或流式序列流式传输到应用程序。
st.write-stream 迭代给定的序列,并将所有块写入应用程序。字符串块将使用打字机效果编写。其他数据类型将使用 st.write 编写。

# 函数签名

st.write_stream (stream)

# 参数: stream

stream (Callable, Generator, Iterable, OpenAI Stream, or LangChain Stream)

要流式传输的生成器或可迭代对象,如果你传递了一个异步生成器,Streamlit 会在内部将其转换为同步生成器。

要使用其他 LLM 库,您可以创建一个包装器来手动定义生成器函数并包含自定义输出解析。

# returns

returns: (str or list)

完整的回应。如果流式输出仅包含文本,则这是一个字符串。否则,这是所有流式对象的列表。返回值与 st.write 的输入完全兼容。

# 示例

可以传递 OpenAI 流,参考教程 生成基本 LLM 聊天应用。或者 您可以传递通用生成器函数作为输入:

import time
import numpy as np
import pandas as pd
import streamlit as st
_LOREM_IPSUM = """
Lorem ipsum dolor sit amet, **consectetur adipiscing** elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
"""
def stream_data ():
    for word in _LOREM_IPSUM.split (" "):
        yield word + " "
        time.sleep (0.02)
    yield pd.DataFrame (
        np.random.randn (5, 5),
        columns=["a", "b", "c", "d", "e"],
    )
    for word in _LOREM_IPSUM.split (" "):
        yield word + " "
        time.sleep (0.02)
if st.button ("Stream data"):
    st.write_stream (stream_data)

如果您的流对象与 不兼容,请围绕流对象定义包装器以创建兼容的生成器函数。st.write_stream

for chunk in unsupported_stream:
    yield preprocess (chunk)

# Magic

魔术命令是 Streamlit 中的一项功能,它允许您编写几乎任何内容(标记、数据、图表),而无需键入任何显式命令。只需将你想显示的内容放在它自己的代码行中,它就会出现在你的应用程序中。这里有一个例子:

# Draw a title and some text to the app:
'''
# This is the document title
This is some _markdown_.
'''
import pandas as pd
df = pd.DataFrame ({'col1': [1,2,3]})
df  # 👈 Draw the dataframe
x = 10
'x', x  # 👈 Draw the string 'x' and then the value of x
# Also works with most supported chart types
import matplotlib.pyplot as plt
import numpy as np
arr = np.random.normal (1, 1, size=100)
fig, ax = plt.subplots ()
ax.hist (arr, bins=20)
fig  # 👈 Draw a Matplotlib chart

# 关闭魔术方法

每当 Streamlit 在自己的行上看到变量或文字值时,它都会使用 st.write 自动将其写入您的应用程序。

此外,魔术方法可以忽略文档字符串。也就是说,它忽略了文件和函数顶部的字符串。

如果你更喜欢更明确地调用 Streamlit 命令,你可以通过以下设置在~/.Streamlit/config.toml 中关闭魔术方法:

[runner]
magicEnabled = false

目前,Magic 仅适用于主 Python 应用程序文件,不适用于导入的文件。

# 文本元素

Streamlit 程序通常会以文本开始,可以使用两个标题级别: st.header st.subheader

纯文本用输入或者 Markdown 输入用 st.text st.Markdown

这里还提供了一个泛用命令,它接受多个参数和多种数据类型: st.write ,文本元素也可以使用 magic 命令代替

# st.header

st.header 将会以标题格式显示文本

# 函数签名

st.header (body, anchor=None, *, help=None, divider=False, width="stretch")

参数名类型描述
bodystr显示为 GitHub 风格 Markdown 的文本 <br>・语法参考:GitHub Flavored Markdown
・额外支持的 Markdown 指令详见 st.markdown 的 body 参数
anchorstr 或 False标题的锚点名称(URL 可通过 #anchor 访问)
・省略时:根据 body 自动生成锚点 <br>・ False :不在 UI 显示锚点
helpstr 或 None标题旁显示的工具提示(默认 None 不显示)
・支持 GitHub 风格 Markdown
・可用语法详见 st.markdown 的 body 参数
dividerbool, "blue", "green", "orange", "red", "violet", "gray"/"grey", 或 "rainbow"标题下方的彩色分隔线 <br>・ True :连续标题循环使用颜色(蓝→绿→橙→...)
・指定颜色:直接使用颜色字符串 <br>・ False (默认):不显示分隔线
width"stretch", "content" 或 int标题元素宽度:
"stretch" (默认):撑满父容器宽度 <br>・ "content" :自适应内容宽度(不超过父容器)
・整数(像素):固定宽度(超过父容器时自动收缩)
※ 注:宽度设置需在 Streamlit 1.27.0+ 版本生效

# 示例

import streamlit as st
st.header ("_Streamlit_ is :blue [cool] :sunglasses:")
st.header ("This is a header with a divider", divider="gray")
st.header ("These headers have rotating dividers", divider=True)
st.header ("One", divider=True)
st.header ("Two", divider=True)
st.header ("Three", divider=True)
st.header ("Four", divider=True)

# st.subheader

st.subheader 将会以副标题格式显示文本

# 函数签名

st.subheader (body, anchor=None, *, help=None, divider=False, width="stretch")

参数名类型描述
bodystr显示为 GitHub 风格 Markdown 的文本 <br>・语法参考:GitHub Flavored Markdown
・额外支持的 Markdown 指令详见 st.markdown 的 body 参数
anchorstr 或 False子标题的锚点名称(URL 可通过 #anchor 访问)
・省略时:根据 body 自动生成锚点 <br>・ False :不在 UI 显示锚点
helpstr 或 None子标题旁显示的工具提示(默认 None 不显示)
・支持 GitHub 风格 Markdown
・可用语法详见 st.markdown 的 body 参数
dividerbool, "blue", "green", "orange", "red", "violet", "gray"/"grey", 或 "rainbow"子标题下方的彩色分隔线 <br>・ True :连续子标题循环使用颜色(蓝→绿→橙→...)
・指定颜色:直接使用颜色字符串 <br>・ False (默认):不显示分隔线
width"stretch", "content" 或 int子标题元素宽度:
"stretch" (默认):撑满父容器宽度 <br>・ "content" :自适应内容宽度(不超过父容器)
・整数(像素):固定宽度(超过父容器时自动收缩)
※ 注:宽度设置需在 Streamlit 1.27.0+ 版本生效

# 示例

import streamlit as st
st.subheader ("_Streamlit_ is :blue [cool] :sunglasses:")
st.subheader ("This is a subheader with a divider", divider="gray")
st.subheader ("These subheaders have rotating dividers", divider=True)
st.subheader ("One", divider=True)
st.subheader ("Two", divider=True)
st.subheader ("Three", divider=True)
st.subheader ("Four", divider=True)

# st.title

st.title 以标题格式显示文本,每个文档都应该有一个单独的 st.title ()

# 函数签名

st.title (body, anchor=None, *, help=None, width="stretch")

参数名类型描述
bodystr显示为 GitHub 风格 Markdown 的文本 <br>・语法参考:GitHub Flavored Markdown
・额外支持的 Markdown 指令详见 st.markdown 的 body 参数
anchorstr 或 False标题的锚点名称(URL 可通过 #anchor 访问)
・省略时:根据 body 自动生成锚点 <br>・ False :不在 UI 显示锚点
helpstr 或 None标题旁显示的工具提示(默认 None 不显示)
・支持 GitHub 风格 Markdown
・可用语法详见 st.markdown 的 body 参数
width"stretch", "content" 或 int标题元素宽度:
"stretch" (默认):撑满父容器宽度 <br>・ "content" :自适应内容宽度(不超过父容器)
・整数(像素):固定宽度(超过父容器时自动收缩)
※ 注:宽度设置需在 Streamlit 1.27.0+ 版本生效

# 示例

import streamlit as st
st.title ("This is a title")
st.title ("_Streamlit_ is :blue [cool] :sunglasses:")

# st.markdown

# 函数签名

st.markdown (body, unsafe_allow_html=False, *, help=None, width="stretch")

参数名类型描述
bodyany显示为 GitHub 风格 Markdown 的文本(语法参考
・非字符串对象自动转换为 str (body)
・额外支持:
- Emoji 短代码( :smile:
- Streamlit 徽标( :streamlit:
- 特殊符号转换( -> →→)
- Material Symbols 图标( :material/icon_name:
- LaTeX 表达式( $...$
- 彩色文本( :color [text]
- 徽章( :color-badge [text]
- 小号文本( :small [text]
unsafe_allow_htmlbool是否渲染 body 中的 HTML(默认 False ):
False :转义 HTML 标签视为纯文本 <br>・ True :直接渲染 HTML 表达式 <br>** 注意 **:自定义 HTML 会影响安全性 < br>※ 纯 HTML/CSS 插入建议改用 st.html ()
helpstr 或 NoneMarkdown 旁显示的工具提示(默认 None 不显示)
・支持 GitHub 风格 Markdown
・可用语法详见 body 参数说明
width"stretch", "content" 或 intMarkdown 元素宽度:
"stretch" (默认):撑满父容器宽度 <br>・ "content" :自适应内容宽度(不超过父容器)
・整数(像素):固定宽度(超过父容器时自动收缩)
※ 注:宽度设置需在 Streamlit 1.27.0+ 版本生效

# 参数:body

支持以下扩展语法(除标准 GFM 外):

功能类型语法示例说明 / 备注
**Emoji 短代码 **:+1: :sunglasses:完整列表
**Streamlit 徽标 **:streamlit:添加 Streamlit 专属标识
** 特殊符号转换 **<- -> >= ~=自动转换为 ← → ≥ ≈ 等符号
**Material 图标 **:material/favorite:图标库
**LaTeX 公式 **$E=mc^2$$$...$$支持函数
** 文本颜色 **:blue [文本] :red-background [文本]支持:blue, green, orange, red, violet, gray/grey, rainbow, primary
** 徽章 **:blue-badge [标签]支持:blue, green, orange, red, violet, gray/grey, primary
** 小号文本 **:small [小字内容]生成较小字号的文本

# 示例

import streamlit as st
md = st.text_area ('Type in your markdown string (without outer quotes)',
                  "Happy Streamlit-ing! :balloon:")
st.code (f"""
import streamlit as st
st.markdown ('''{md}''')
""")
st.markdown (md)

# st.badge

st.badge 显示带有图标和标签的彩色布局。

这是一个围绕颜色标识 Markdown 指令的类别,等效以下内容的:

  • st.markdown (":blue-badge [Home]")
  • st.badge ("Home", color="blue")

# 函数签名

st.badge (label, *, icon=None, color="blue", width="content")

参数名类型描述
labelstr徽章显示的文本标签 <br>・支持部分 GitHub 风格 Markdown:
- ** 粗体 * 斜体 *、~~ 删除线~~、 行内代码
・不支持需要方括号 [ ] 的指令(因自动转义)
・完整语法详见 st.markdown 的 body 参数
iconstr 或 None标签旁显示的图标(默认 None 不显示):
・** 单字符 Emoji**: "🚨""🔥"
・**Material Symbols 图标 **: :material/icon_name:
- 示例: icon=":material/thumb_up:"
- 图标库
colorstr徽章颜色(默认 "blue"
・可选值: blue , green , orange , red , violet , gray / grey , primary
primary :使用主题主色(可通过 theme.primaryColor 配置)
width"content", "stretch" 或 int徽章元素宽度:
"content" (默认):自适应内容宽度(不超过父容器)
"stretch" :撑满父容器宽度 <br>・整数(像素):固定宽度(超过父容器时自动收缩)
※ 注:宽度设置需在 Streamlit 1.27.0+ 版本生效

# 参数:label

Markdown 类型示例渲染效果
** 粗体 **** 重要 **** 重要 **
* 斜体 ** 强调 ** 强调 *
~~ 删除线~~~~ 旧值~~~~ 旧值~~
行内代码```print ()` ``print ()
链接 / 图片[文本](url)显示为原始文本

# 参数:icon

类型代码示例显示效果
Emojiicon="⭐"⭐ 标签文本
Material 图标icon=":material/rocket:"🚀 标签文本

# 示例

import streamlit as st
st.badge ("New")
st.badge ("Success", icon=":material/check:", color="green")
st.markdown (
    ":violet-badge [:material/star: Favorite] :orange-badge [⚠️ Needs review] :gray-badge [Deprecated]"
)

# st.caption

st.caption 以小字体显示文本,通常应用于标题、旁白、脚注、旁注和其他解释性文本。

# 函数签名

st.caption (body, unsafe_allow_html=False, *, help=None, width="stretch")

参数名类型描述
bodystr显示为 GitHub 风格 Markdown 的说明文本(语法参考
・额外支持的 Markdown 指令详见 st.markdown 的 body 参数
unsafe_allow_htmlbool是否渲染 body 中的 HTML(默认 False ):
False :转义 HTML 标签视为纯文本 <br>・ True :直接渲染 HTML 表达式 <br>** 注意 **:自定义 HTML 会影响安全性 < br>※ 纯 HTML/CSS 插入建议改用 st.html ()
helpstr 或 None说明文本旁显示的工具提示(默认 None 不显示)
・支持 GitHub 风格 Markdown
・可用语法详见 body 参数说明
width"stretch", "content" 或 int说明文本元素宽度:
"stretch" (默认):撑满父容器宽度 <br>・ "content" :自适应内容宽度(不超过父容器)
・整数(像素):固定宽度(超过父容器时自动收缩)
※ 注:宽度设置需在 Streamlit 1.27.0+ 版本生效

# 示例

import streamlit as st
st.caption ("This is a string that explains something above.")
st.caption ("A caption with _italics_ :blue [colors] and emojis :sunglasses:")

# st.code

st.code 显示带有可选语法突出显示的代码块。

# 函数签名

st.code (body, language="python", *, line_numbers=False, wrap_lines=False, height="content", width="stretch")

参数名类型描述
bodystr要显示为代码或等宽文本的字符串
languagestr 或 None代码语言(用于语法高亮),默认为 "python"
None :显示为纯等宽文本 <br>・支持语言列表参考 react-syntax-highlighter
line_numbersbool是否在代码块左侧显示行号(默认 False 不显示)
wrap_linesbool是否自动换行(默认 False 不换行)
height"content", "stretch" 或 int代码块高度:
"content" (默认):自适应内容高度 <br>・ "stretch" :自适应内容高度或父容器高度(取较大值)
・整数(像素):固定高度(内容超出时启用滚动)
** 注意 **:避免设置超过 500px 的高度(移动端体验)
width"stretch", "content" 或 int代码块宽度:
"stretch" (默认):撑满父容器宽度 <br>・ "content" :自适应内容宽度(不超过父容器)
・整数(像素):固定宽度(超过父容器时自动收缩)

# 示例

import streamlit as st
code = '''def hello ():
    print ("Hello, Streamlit!")'''
st.code (code, language="python")

# st.divider

st.divider 用于显示水平标尺,您可以在脚本中使用 st.write(“---”)甚至只是 “---”(通过魔法)来实现相同的效果。

# 函数签名

st.divider (*, width="stretch")

参数名类型描述
width"stretch" 或 int分隔线元素宽度:
"stretch" (默认):撑满父容器宽度 <br>・整数(像素):固定宽度(超过父容器时自动收缩为父容器宽度)

# 示例

import streamlit as st
st.write ("This is some text.")
st.slider ("This is a slider", 0, 100, (25, 75))
st.divider ()  # Draws a horizontal rule
st.write ("This text is between the horizontal rules.")
st.divider ()  # Another horizontal rule

# st.echo

st.echo 绑定 with 语句。常用于输出页面源码内容。

# 函数签名

st.echo (code_location="above")

参数名类型描述
code_location"above" 或 "below"显示执行代码的位置:
"above" (默认):在输出结果上方显示代码 <br>・ "below" :在输出结果下方显示代码

# 示例

import streamlit as st
with st.echo ():
    st.write ('This code will be printed')

有时,你希望你的 Streamlit 应用程序既包含你常用的 Streamlite 图形元素,也包含生成这些元素的代码,这是就可以使用 st.echo ()

假设你有以下文件,你想让人们看到你 Streamlit 代码的中间部分:

import streamlit as st
def get_user_name ():
    return 'John'
# ------------------------------------------------
# 需要让人们看到下面的代码内容
def get_punctuation ():
    return '!!!'
greeting = "Hi there,"
user_name = get_user_name ()
punctuation = get_punctuation ()
st.write (greeting, user_name, punctuation)
# 到这里为止
# ------------------------------------------------
foo = 'bar'
st.write ('Done!')

使用 st.echo 使代码的中间部分在应用程序中可见:

import streamlit as st
def get_user_name ():
    return 'John'
with st.echo ():
    #此块中的所有内容都将执行并打印到屏幕上。
    def get_punctuation ():
        return '!!!'
    greeting = "Hi there,"
    value = get_user_name ()
    punctuation = get_punctuation ()
    st.write (greeting, value, punctuation)
# 无需继续打印
foo = 'bar'
st.write ('Done!')

# st.latex

st.latex 显示格式为 LaTeX 的数学表达式,支持的 LaTeX 函数列在 https://katex.org/docs/supported.html.

# 函数签名 [来源]

st.latex (body, *, help=None, width="stretch")

参数名类型描述
bodystr 或 SymPy 表达式要显示为 LaTeX 的字符串或 SymPy 表达式 <br>・建议使用原始字符串( r"..." )避免转义问题 <br>・示例: st.latex (r"\sum_{i=1}^{n} i^2 = \frac {n (n+1)(2n+1)}{6}")
helpstr 或 NoneLaTeX 表达式旁显示的工具提示(默认 None 不显示)
・支持 GitHub 风格 Markdown
・可用语法详见 st.markdown 的 body 参数
width"stretch", "content" 或 intLaTeX 元素宽度:
"stretch" (默认):撑满父容器宽度 <br>・ "content" :自适应内容宽度(不超过父容器)
・整数(像素):固定宽度(超过父容器时自动收缩)
※ 注:宽度设置需在 Streamlit 1.27.0+ 版本生效

# 示例

import streamlit as st
st.latex (r'''
    a + ar + a r^2 + a r^3 + \cdots + a r^{n-1} =
    \sum_{k=0}^{n-1} ar^k =
    a \left (\frac {1-r^{n}}{1-r}\right)
    ''')

# st.text

st.text 无需 Markdown 或 HTML 解析即可编写文本,对于等宽文本,请使用 st.code。

# 函数签名

st.text (body, *, help=None, width="content")

参数名类型描述
bodystr要显示的纯文本内容
helpstr 或 None文本旁显示的工具提示(默认 None 不显示)
・支持 GitHub 风格 Markdown
・可用语法详见 st.markdown 的 body 参数
width"content", "stretch" 或 int文本元素宽度:
"content" (默认):自适应内容宽度(不超过父容器)
"stretch" :撑满父容器宽度 <br>・整数(像素):固定宽度(超过父容器时自动收缩)

# 示例

import streamlit as st
st.text ("This is text\n [and more text](that's not a Markdown link).")

# st.help

st.help 显示给定对象的帮助和其他信息。

根据传入的对象类型,这将显示对象的名称、类型、值、签名、docstring 和成员变量、方法,以及成员和方法的值 /docstring。

# 函数签名

st.help (obj=, *, width="stretch")

参数名类型描述
objany需要显示帮助信息的对象 <br>・留空时显示 Streamlit 自身的帮助信息
width"stretch" 或 int帮助信息元素宽度:
"stretch" (默认):撑满父容器宽度 <br>・整数(像素):固定宽度(超过父容器时自动收缩为父容器宽度)

# 示例

import streamlit as st
import pandas
st.help (pandas.DataFrame)

# st.html

st.html 用于将 HTML 插入您的应用程序。

向应用程序添加自定义 HTML 会影响安全性、样式和可维护性。我们使用 DOMPurify 对 HTML 进行净化,但插入 HTML 仍然是开发人员的风险。将不受信任的代码传递给 st.html 或动态加载外部代码会增加应用程序中的漏洞风险。

st.html 内容不是 iframe 格式的。目前不支持执行 JavaScript。

# 函数签名

st.html (body, *, width="stretch")

参数名类型描述
bodyany要插入的 HTML 内容:
・HTML 代码字符串 <br>・HTML 文件路径(str 或 Path 对象,支持绝对 / 相对路径)
・任意对象(优先使用 _repr_html_() ,其次 str (body)
※ 空内容会触发错误 <br>※ CSS 文件自动添加 <style> 标签 <br>※ 纯 CSS 内容会发送到事件容器避免占用主空间
width"stretch", "content" 或 intHTML 元素宽度:
"stretch" (默认):撑满父容器宽度 <br>・ "content" :自适应内容宽度(不超过父容器)
・整数(像素):固定宽度(超过父容器时自动收缩)

# 示例

import streamlit as st
st.html (
    "<p><span style='text-decoration: line-through double red;'>Oops</span>!</p>"
)

# 30 天学习 Streamlit

# day1: 设置本地开发环境

在我们正式开始构建 Streamlit 应用之前,我们需要首先设置一个开发环境,让我们从安装和配置 conda 环境开始。

# 安装 conda

前往 https://docs.conda.io/en/latest/miniconda.html ,选择与你操作系统(Windows, Mac 或 Linux)对应的 conda 版本
下载安装器并运行,完成 conda 的安装

装好了 conda 后,让我们来创建一个 conda 环境来管理所有 Python 库依赖。

比如按照如下指令,使用 Python 3.9 版本创建一个新的环境: conda create -n stenv python=3.9

其中 create -n stenv 表示创建一个名为 stenv 的 conda 环境,而 python=3.9 会指定 conda 环境使用 3.9 版本的 Python。

# 激活 conda 环境

要使用上一步刚创建好的名为 stenv 的 conda 环境,则需要使用如下的命令: conda activate stenv

# 安装 Streamlit 库

激活环境之后就是时候安装 streamlit 库了: pip install streamlit

# 启动示例 Streamlit 应用

用如下指令来启动示例 Streamlit 应用: streamlit hello

# day2: 第一个 Streamlit 应用

启动你的 IDE,新建一个名为 streamlit_app.py 的文件,写入如下几行代码:

import streamlit as st
st.write ('Hello world!')

然后保存文件。在 vscode 中按下 Ctrl + ~ 启动命令行终端,前往终端,敲入命令: streamlit run streamlit_app.py

然后应当弹出一个浏览器窗口,其中为你新创建的 Streamlit 应用。

恭喜你! 你刚刚搭建了人生中第一个 Streamlit 应用!

# day3: st.button

st.button 会显示一个按钮组件,我们今天要搭建一个简单的应用,根据按钮是否按下的状态,显示不同的文字消息,流程如下:

  1. 默认情况下输出 Goodbye
  2. 一旦按下按钮,则会变为显示 Why hello there

# 示例代码

实现功能的示例代码如下:

import streamlit as st
# 标题文字
st.header ('st.button')
# 按钮事件
if st.button ('Say hello'):
     st.write ('Why hello there')
else:
     st.write ('Goodbye')

# 代码解释

创建 Streamlit 应用时要做的第一件事就是将 streamlit 库导入为 st: import streamlit as st

然后紧跟着的是应用的标题文字: st.header ('st.button')

接下来,我们会使用条件分支语句 if 和 else 来显示不同的消息:

if st.button ('Say hello'):
     st.write ('Why hello there')
else:
     st.write ('Goodbye')

由这段代码可见, st.button () 语句接收了一个值为 Say hellolabel 参数,会作为显示在按钮上的文字。

st.write 命令被用作显示文字消息,取决于按钮是否按下,显示的要么是 Why hello there ,要么是 Goodbye ,即语句: st.write ('Why hello there')st.write ('Goodbye')

需要注意的是,以上 st.write 语句是在 ifelse 条件分支内的,才能达到前述显示不同消息的效果。

# 举一反三

观察发现,我们可以赋值一个变量 btn = st.button ('Click me') ,根据 btn 是否被点击,输出文字:

btn = st.button ('Click me')
if btn:
    st.write ('Button clicked!')

但是上述代码中,如果一直点击 btn,也不会持续生成文字内容,这是因为:

在 Streamlit 中,按钮 st.button 的行为是瞬时状态的,点击后它只在当前脚本运行周期内返回 True。当脚本重新运行时(每次交互(如点击按钮)都会从头到尾重新执行整个脚本),原有的 st.write ('Button clicked!') 被清除,脚本即再次判断 btn 被按下且输出了一次 st.write ('Button clicked!')

其处理逻辑为:

  • 第一次点击:btn=True → 显示文本
  • 后续点击:脚本重新执行 → st.write ('Button clicked!') 被清除
  • btn 为 True → 条件满足 → 写入 st.write ('Button clicked!')

想要解决这个问题,我们可以使用会话状态 (Session State) 记录点击次数:

btn = st.button ('Click me')
# 初始化计数器
if 'click_count' not in st.session_state:
    st.session_state.click_count = 0
# 按钮每次点击都会增加计数
if btn:
    st.session_state.click_count += 1
    st.write (f'Button clicked {st.session_state.click_count} times!')

使用上述示例代码,可以确定每次点击按钮时,输出的数字不同,即每次点击后脚本都会被重新执行。