安装
pip install streamlit
基础
基本用法
运行
推荐
streamlit run your_script.py [-- script args]
注意:当你向脚本传递一些自定义参数时,这些参数必须以两个连字符之后传递。否则,这些参数会被解释为 Streamlit 本身的参数。
作为模块运行
# 启动服务
python -m streamlit run your_script.py
# 等价于
streamlit run your_script.py
将远程脚本交给 streamlit 运行
streamlit run https://raw.githubusercontent.com/streamlit/demo-uber-nyc-pickups/master/streamlit_app.py
数据可视化
魔法命令
每当 Streamlit 在单独一行的位置看到变量或字面值时,它会自动使用 st.write() 将该内容写入你的应用程序。
import streamlit as st
import pandas as pd
df = pd.DataFrame({
'first column': [1, 2, 3, 4],
'second column': [10, 20, 30, 40]
})
df
# 命令行使用streamlit run执行
$ streamlit run test.py
使用 st.write() 渲染内容
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({
'first column': [1, 2, 3, 4],
'second column': [10, 20, 30, 40]
}))
st.dataframe():创建 DataFrame、调整样式
创建 DataFrame
import streamlit as st
import numpy as np
dataframe = np.random.randn(10, 20)
st.dataframe(dataframe)
调整样式
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.dataframe(dataframe.style.highlight_max(axis=0))
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)
st.line_chart():绘制折线图
import streamlit as st
import numpy as np
import pandas as pd
chart_data = pd.DataFrame(
np.random.randn(20, 3),
columns=['a', 'b', 'c'])
st.line_chart(chart_data)
st.map():绘制地图
import streamlit as st
import numpy as np
import pandas as pd
map_data = pd.DataFrame(
np.random.randn(1000, 2) / [50, 50] + [37.76, -122.4],
columns=['lat', 'lon'])
st.map(map_data)
组件
st.slider():滑动条
import streamlit as st
x = st.slider('x') # 👈 this is a widget
st.write(x, 'squared is', x * x)
st.button():按键
import streamlit as st
x = st.slider('x') # 👈 this is a widget
st.write(x, 'squared is', x * x)
st.selectbox():下拉菜单
import streamlit as st
st.title('下拉菜单平方计算器')
st.write('选择一个字母,查看其对应数值的平方')
# 创建下拉菜单,使用元组列表同时显示标签和对应的值
option = st.selectbox(
'请选择一个选项:',
options=[('a', 1), ('b', 2), ('c', 3)],
format_func=lambda x: x[0] # 只显示字母部分
)
# 提取选择的数值
selected_value = option[1]
selected_label = option[0]
# 显示结果
st.write(f"选项 '{selected_label}' 对应的值是 {selected_value}")
st.write(f"{selected_value} 的平方是 {selected_value * selected_value}")
使用组件添加键
import streamlit as st
# 通过key,为st添加属性
st.text_input("Your name", key="name")
# You can access the value at any point with:
st.session_state.name
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
st.selectbox() 使用选择框选择数据
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
st.sidebar() 将组件放置在左侧边栏
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)
)
st.columns 让你可以将小部件并排放置
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.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 使用两个缓存装饰器进行数据缓存:
st.cache_data:缓存返回数据,可以用于缓存可序列化对象,例如str、int、float、DataFrame、dict、listst.cache_resource:缓存全局资源,可以用于缓存 ML 模型或数据库连接,可以用于缓存不可序列化对象,对象缓存后将在所有会话中存在
示例:
@st.cache_data
def long_running_function(param1, param2):
return …
使用 st.cache_data 装饰器后,Streamlit 记录了以下内容:函数的名称("long_running_function")、输入的值(param1,param2)、函数内的代码。
在运行代码之前,Streamlit 会检查缓存,如果针对给定的函数和输入值找到了缓存的结果,将返回该缓存结果,而不会重新运行函数的代码。
会话
示例:统计页面运行次数。每次点击按钮时,脚本都会重新运行
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")
说明:session_state 可以缓存状态
- 首次运行:初始化
session_state.counter属性为 0,此时相当于在字典中创建了键值对("counter": 0),代码执行过程中,计数器递增("counter": 1) - 第二次运行:
"counter"已经是session_state中的键,不会重新初始化。代码执行过程中,计数器递增("counter": 2)
会话的应用场景:缓存状态和变量,使之在当前 Session 中可用。
连接
使用 st.connection 连接数据库,示例:
import streamlit as st
conn = st.connection("my_database")
df = conn.query("select * from my_table")
st.dataframe(df)
注意:st.connection 连接数据库时需要的账号、密码、host 等信息保存在 toml 文件,目录结构如下:
your-LOCAL-repository/
├── .streamlit/
│ └── secrets.toml # Make sure to gitignore this!
└── streamlit_app.py
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
多页面应用
使用 st.Page 和 st.navigation 创建多页应用程序:
- 为每个页面创建单独的 Python 文件
- 使用
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 run your_script.py [-- script args]
注意:当你向脚本传递一些自定义参数时,这些参数必须以两个连字符之后传递。否则,这些参数会被解释为 Streamlit 本身的参数。
作为模块运行
# 启动服务
python -m streamlit run your_script.py
# 等价于
streamlit run your_script.py
将远程脚本交给 streamlit 运行
streamlit run https://raw.githubusercontent.com/streamlit/demo-uber-nyc-pickups/master/streamlit_app.py
应用部署
streamlit run script.py启动本地服务,打开网页- 点击页面右上角的 “Deploy”
- 点击弹窗中左侧 Streamlit Community Cloud 下方的 “Deploy Now”
- 填写代码仓库(Repository)、分支(Branch)、启动脚本文件名(main file path)、子域名(App URL),即可创建一个公网可以访问的链接
创建多页面应用
st.Page 和 st.navigation
st.Page:通过st.Page将任何 Python 文件或 Callable 声明为应用中的页面st.navigation:通过st.navigation将主页与其他页面连接
pages 目录
对于 pages/ 目录中的每个 Python 文件,Streamlit 都会创建一个页面。Streamlit 根据文件名确定页面标签和 URL,并在应用侧边栏顶部自动填充导航菜单。
pages 目录示例如下:
your_working_directory/
├── pages/
│ ├── a_page.py
│ └── another_page.py
└── your_homepage.py
Streamlit 根据文件名确定导航菜单中的页面顺序。如果需要手动排列页面顺序,可以使用 st.page_link 手动构建自定义导航菜单。
当使用 pages 目录时,Streamlit 会自动对 pages 目录中的文件名进行解析。
Streamlit 默认文件名可以拆分为以下部分:
- number:一个非负整数。
- separator:下划线(
"_")、连字符("-")和空格(" ")的任意组合。 - identifier:到
".py"之前的所有内容。如果不是文件而是可调用对象,函数名即 identifier,包括任何前导或尾随的下划线。 - 文件名后缀:
".py"
Streamlit 按照以下逻辑将文件名解析为页面标签和标题:
- 如果文件名有 identifier,解析结果会有 identifier。identifier 内部的任何下划线都视为空格,前导和尾随的下划线不会显示,连续的下划线会显示为一个空格
- 如果文件名只有 number 没有 identifier,解析结果仅有 number,且不做修改。如果存在前导零,则会保留
- 如果文件名只有 separator 没有 number 和 identifier,则不会在侧边栏导航中显示该页面
以下文件名和可调用对象在侧边栏导航中都会显示为 “Awesome page”,如果部署在本地,访问的完整 URL 将为 localhost:8501/awesome_page:
| 文件名 | 解析逻辑 |
|---|---|
"Awesome page.py" | 下划线视为空格,解析得到 identifier:Awesome page |
"Awesome_page.py" | 下划线转为空格,解析得到 identifier:Awesome page |
"02Awesome_page.py" | 解析得到 number:02,identifier:Awesome page |
"--Awesome_page.py" | 解析得到 separator:—,identifier:Awesome page |
"1_Awesome_page.py" | 解析得到 number:1,separator:_,identifier:Awesome page |
"33 - Awesome page.py" | 解析得到 number:33,separator: - ,identifier:Awesome page |
Awesome_page() | 可调用对象,identifier:Awesome page |
_Awesome_page() | 可调用对象,保留_,解析得到 identifier:Awesome page |
__Awesome_page__() | 可调用对象,保留__,解析得到 identifier:Awesome page |
页面术语
- 页面标签:这是页面在导航菜单中的识别方式。
- 页面标题:这是 HTML
<title>元素的内容以及页面在浏览器标签页中的识别方式。 - 页面 URL 路径:这是页面相对于应用根 URL 的相对路径。
- 页面 favicon:这是浏览器标签页中页面标题旁边的图标。
- 页面图标:这是导航菜单中页面标签旁边的图标。
如图:1. 页面标签,2. 页面标题,3. 页面 URL 路径名,4. 页面网站图标,5. 页面图标
应用设计
动态更新元素
以下元素支持在循环中进行动态更新:
| 元素 | 更新操作 |
|---|---|
st.empty | 可以容纳单个元素,支持覆写,始终显示最后写入的内容。还可以通过 .empty() 方法来清除 |
st.dataframe | 通过 .add_rows() 方法更新并追加数据 |
st.table | 通过 .add_rows() 方法更新并追加数据 |
st.progress | 通过 .progress() 调用进行更新。可以通过 .empty() 来清除 |
st.status | 通过 .update() 更改标签和状态 |
st.toast | 通过 .toast() 调用就地更新 |
.add_rows() 方法
st.dataframe、st.table 以及所有图表函数都可以通过在其输出上使用 .add_rows() 方法进行追加更新,示例如下:
import streamlit as st
import pandas as pd
import numpy as np
import time
df = pd.DataFrame(np.random.randn(15, 3), columns=(["A", "B", "C"]))
my_data_element = st.line_chart(df)
for tick in range(10):
time.sleep(.5)
add_df = pd.DataFrame(np.random.randn(1, 3), columns=(["A", "B", "C"]))
my_data_element.add_rows(add_df)
st.button("Regenerate")
按钮行为
1)按钮显示信息
import streamlit as st
animal_shelter = ['cat', 'dog', 'rabbit', 'bird']
animal = st.text_input('Type an animal')
if st.button('Check availability'):
have_it = animal.lower() in animal_shelter
'We have that animal!' if have_it else 'We don\'t have that animal.'
2)有状态按钮
按钮点击后状态为 False,通过 on_click 回调函数重置状态为 True:
import streamlit as st
if 'clicked' not in st.session_state:
st.session_state.clicked = False
def click_button():
st.session_state.clicked = True
st.button('Click me', on_click=click_button)
if st.session_state.clicked:
# The message and nested widget will remain on the page
st.write('Button clicked!')
st.slider('Select a value')
3)与其他控件进行交互
import streamlit as st
if 'button' not in st.session_state:
st.session_state.button = False
def click_button():
st.session_state.button = not st.session_state.button
st.button('Click me', on_click=click_button)
if st.session_state.button:
# The message and nested widget will remain on the page
st.write('Button is on!')
st.slider('Select a value')
else:
st.write('Button is off!')
4)控制流程
使用 st.session_state 的属性值控制阶段,例如有以下 4 个阶段:
- 在用户开始之前。
- 用户输入他们的名字。
- 用户选择一个颜色。
- 用户收到一条感谢信息。
示例代码:
import streamlit as st
if 'stage' not in st.session_state:
st.session_state.stage = 0
def set_state(i):
st.session_state.stage = i
if st.session_state.stage == 0:
st.button('Begin', on_click=set_state, args=[1]) # args[0]会传递给set_state函数
if st.session_state.stage >= 1:
name = st.text_input('Name', on_change=set_state, args=[2])
if st.session_state.stage >= 2:
st.write(f'Hello {name}!')
color = st.selectbox(
'Pick a Color',
[None, 'red', 'orange', 'green', 'blue', 'violet'],
on_change=set_state, args=[3]
)
if color is None:
set_state(2)
if st.session_state.stage >= 3:
st.write(f':{color}[Thank you!]')
st.button('Start Over', on_click=set_state, args=[0])
5)尽量使用回调函数修改 st.session_state 的状态
未使用回调函数:
import streamlit as st
import pandas as pd
if 'name' not in st.session_state:
st.session_state['name'] = 'John Doe'
st.header(st.session_state['name'])
if st.button('Jane'):
st.session_state['name'] = 'Jane Doe'
if st.button('John'):
st.session_state['name'] = 'John Doe'
st.header(st.session_state['name'])
使用回调函数:
import streamlit as st
import pandas as pd
if 'name' not in st.session_state:
st.session_state['name'] = 'John Doe'
def change_name(name):
st.session_state['name'] = name
st.header(st.session_state['name'])
st.button('Jane', on_click=change_name, args=['Jane Doe'])
st.button('John', on_click=change_name, args=['John Doe'])
st.header(st.session_state['name'])
6)修改其他组件的状态
方法 1:为按钮使用一个键,并将逻辑放在组件之前
如果你给按钮分配了一个键,你可以通过在 st.session_state 中使用它的值来根据按钮的状态进行条件代码。这意味着依赖于你的按钮的逻辑可以放在脚本中该按钮之前。
import streamlit as st
# Use the get method since the keys won't be in session_state
# on the first script run
if st.session_state.get('clear'):
st.session_state['name'] = ''
if st.session_state.get('streamlit'):
st.session_state['name'] = 'Streamlit'
st.text_input('Name', key='name')
st.button('Clear name', key='clear')
st.button('Streamlit!', key='streamlit')
方法 2:使用回调函数
import streamlit as st
st.text_input('Name', key='name')
def set_name(name):
st.session_state.name = name
st.button('Clear name', on_click=set_name, args=[''])
st.button('Streamlit!', on_click=set_name, args=['Streamlit'])
方法 3:使用容器
通过使用 st.container,可以让小部件在你的脚本和前端视图(网页)中按不同顺序显示:
import streamlit as st
begin = st.container()
if st.button('Clear name'):
st.session_state.name = ''
if st.button('Streamlit!'):
st.session_state.name = ('Streamlit')
# The widget is second in logic, but first in display
begin.text_input('Name', key='name')
7)添加其他小部件
import streamlit as st
def display_input_row(index):
left, middle, right = st.columns(3)
left.text_input('First', key=f'first_{index}')
middle.text_input('Middle', key=f'middle_{index}')
right.text_input('Last', key=f'last_{index}')
if 'rows' not in st.session_state:
st.session_state['rows'] = 0
def increase_rows():
st.session_state['rows'] += 1
st.button('Add person', on_click=increase_rows)
for i in range(st.session_state['rows']):
display_input_row(i)
# Show the results
st.subheader('People')
for i in range(st.session_state['rows']):
st.write(
f'Person {i+1}:',
st.session_state[f'first_{i}'],
st.session_state[f'middle_{i}'],
st.session_state[f'last_{i}']
)
8)【不推荐】按钮中嵌套按钮
import streamlit as st
if st.button('Button 1'):
st.write('Button 1 was clicked')
if st.button('Button 2'):
# This will never be executed.
st.write('Button 2 was clicked')
9)【不推荐】按钮中嵌套其他组件
import streamlit as st
if st.button('Sign up'):
name = st.text_input('Name')
if name:
# This will never be executed.
st.success(f'Welcome {name}')
10)【不推荐】按钮中嵌套逻辑处理
import streamlit as st
import pandas as pd
file = st.file_uploader("Upload a file", type="csv")
if st.button('Get data'):
df = pd.read_csv(file)
# This display will go away with the user's next action.
st.write(df)
if st.button('Save'):
# This will always error.
df.to_csv('data.csv')
数据框
1)使用 st.dataframe 展示数据
import streamlit as st
import pandas as pd
df = pd.DataFrame(
[
{"command": "st.selectbox", "rating": 4, "is_widget": True},
{"command": "st.balloons", "rating": 5, "is_widget": False},
{"command": "st.time_input", "rating": 3, "is_widget": True},
]
)
st.dataframe(df, use_container_width=True)
2)使用 st.data_editor 编辑数据
df = pd.DataFrame(
[
{"command": "st.selectbox", "rating": 4, "is_widget": True},
{"command": "st.balloons", "rating": 5, "is_widget": False},
{"command": "st.time_input", "rating": 3, "is_widget": True},
]
)
edited_df = st.data_editor(df, num_rows="dynamic") # num_rows参数设置为"dynamic",可以通过UI添加或删除行
favorite_command = edited_df.loc[edited_df["rating"].idxmax()]["command"]
st.markdown(f"Your favorite command is **{favorite_command}** 🎈")
借助 session_state,可以访问编辑后的数据:
st.data_editor(df, key="my_key", num_rows="dynamic") # 👈 Set a key
st.write("Here's the value in Session State:")
st.write(st.session_state["my_key"]) # 👈 Show the value in Session State
编辑后的数据在 session_state 中会返回一个 JSON 对象,包含三个字段:
edited_rows:包含所有编辑的字典。键是零基行索引,值是映射列名到编辑的字典(例如{0: {"col1": ..., "col2": ...}})added_rows:新添加行的列表。每个值都是一个与上面相同格式的字典(例如[{"col1": ..., "col2": ...}])deleted_rows:一个已从表格中删除的行号列表(例如[0, 2])
3)配置空的 DataFrame 用于收集用户输入
import streamlit as st
import pandas as pd
df = pd.DataFrame(columns=['name','age','color'])
colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
config = {
'name' : st.column_config.TextColumn('Full Name (required)', width='large', required=True),
'age' : st.column_config.NumberColumn('Age (years)', min_value=0, max_value=122),
'color' : st.column_config.SelectboxColumn('Favorite Color', options=colors)
}
result = st.data_editor(df, column_config = config, num_rows='dynamic')
if st.button('Get results'):
st.write(result)
多线程
1)所有线程完成计算后,统一显示
import streamlit as st
import time
from threading import Thread
class WorkerThread(Thread):
def __init__(self, delay):
super().__init__()
self.delay = delay
self.return_value = None
def run(self):
start_time = time.time()
time.sleep(self.delay)
end_time = time.time()
self.return_value = f"start: {start_time}, end: {end_time}"
delays = [5, 4, 3, 2, 1]
threads = [WorkerThread(delay) for delay in delays]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
for i, thread in enumerate(threads):
st.header(f"Thread {i}")
st.write(thread.return_value)
st.button("Rerun")
2)所有线程完成计算后,各自显示(每个线程使用一个容器)
import streamlit as st
import time
from threading import Thread
class WorkerThread(Thread):
def __init__(self, delay):
super().__init__()
self.delay = delay
self.return_value = None
def run(self):
start_time = time.time()
time.sleep(self.delay)
end_time = time.time()
self.return_value = f"start: {start_time}, end: {end_time}"
delays = [5, 4, 3, 2, 1]
result_containers = []
for i, delay in enumerate(delays):
st.header(f"Thread {i}")
result_containers.append(st.container())
threads = [WorkerThread(delay) for delay in delays]
for thread in threads:
thread.start()
thread_lives = [True] * len(threads)
while any(thread_lives):
for i, thread in enumerate(threads):
if thread_lives[i] and not thread.is_alive():
result_containers[i].write(thread.return_value)
thread_lives[i] = False
time.sleep(0.5)
for thread in threads:
thread.join()
st.button("Rerun")
连接、密钥、身份验证
连接
1. 本地 SQLite 数据库
安装依赖:
pip install SQLAlchemy==1.4.0
配置 .streamlit/secrets.toml 文件:
[connections.pets_db]
url = "sqlite:///pets.db"
代码中使用 st.connection 连接数据库:
# streamlit_app.py
import streamlit as st
# Create the SQL connection to pets_db as specified in your secrets file.
conn = st.connection('pets_db', type='sql')
# Insert some data with conn.session.
with conn.session as s:
s.execute('CREATE TABLE IF NOT EXISTS pet_owners (person TEXT, pet TEXT);')
s.execute('DELETE FROM pet_owners;')
pet_owners = {'jerry': 'fish', 'barbara': 'cat', 'alex': 'puppy'}
for k in pet_owners:
s.execute(
'INSERT INTO pet_owners (person, pet) VALUES (:owner, :pet);',
params=dict(owner=k, pet=pet_owners[k])
)
s.commit()
# Query and display the data you inserted
pet_owners = conn.query('select * from pet_owners')
st.dataframe(pet_owners)
2. 全局密钥,管理多个应用和多个数据库
假设已有配置文件 ~/.streamlit/secrets.toml:
[connections.local]
url = "mysql://me:****@localhost:3306/local_db"
[connections.staging]
url = "mysql://jdoe:******@staging.acmecorp.com:3306/staging_db"
配置应用程序连接,使其名称来自指定的环境变量:
# streamlit_app.py
import streamlit as st
conn = st.connection("env:DB_CONN", "sql")
df = conn.query("select * from mytable")
# ...
通过设置 DB_CONN 环境变量,指定在运行时连接到本地或测试环境:
# connect to local
DB_CONN=local streamlit run streamlit_app.py
# connect to staging
DB_CONN=staging streamlit run streamlit_app.py
密钥
密钥文件:macOS/Linux 使用 ~/.streamlit/secrets.toml,Windows 使用 %userprofile%/.streamlit/secrets.toml
# Everything in this section will be available as an environment variable
db_username = "Jane"
db_password = "mypassword"
# You can also add other sections if you like.
# The contents of sections as shown below will not become environment variables,
# but they'll be easily accessible from within Streamlit anyway as we show
# later in this doc.
[my_other_secrets]
things_i_like = ["Streamlit", "Python"]
使用密钥:
import streamlit as st
# Everything is accessible via the st.secrets dict:
st.write("DB username:", st.secrets["db_username"])
st.write("DB password:", st.secrets["db_password"])
# And the root-level secrets are also accessible as environment variables:
import os
st.write(
"Has environment variables been set:",
os.environ["db_username"] == st.secrets["db_username"],
)
用户认证和信息
1. OpenID Connect
Streamlit 支持使用 OpenID Connect (OIDC) 进行用户认证,一些流行的 OIDC 提供商包括:
- Google 身份验证
- Microsoft Entra ID
- Okta
- Auth0
2. 用户认证命令
st.login():将用户重定向到你的身份提供者。登录后,Streamlit 存储一个身份 cookie,然后将其重定向到新会话中你的应用主页st.user:类似字典,用于访问用户信息。有一个持久属性.is_logged_in,你可以检查用户的登录状态。登录时根据你的身份提供者的配置,其他属性可用st.logout():从用户的浏览器中移除身份 cookie,并将他们重定向到新会话中应用主页
3. 示例 1:使用 Google Identity
编辑配置文件:
[auth]
redirect_uri = "http://localhost:8501/oauth2callback"
cookie_secret = "xxx"
client_id = "xxx"
client_secret = "xxx"
server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration"
注意:确保 redirect_uri 中的端口与你正在使用的端口匹配。cookie_secret 应该是一个强随机生成的密钥。redirect_uri 和 cookie_secret 应该已经输入到你的 Google Cloud 客户端配置中。在创建客户端后,你必须从 Google Cloud 中复制 client_id 和 client_secret。对于某些身份提供者,server_metadata_url 可能对你的客户端是唯一的。
创建一个简单的登录流程:
import streamlit as st
if not st.user.is_logged_in:
if st.button("Log in with Google"):
st.login()
st.stop()
if st.button("Log out"):
st.logout()
st.markdown(f"Welcome! {st.user.name}")
改进:使用回调函数简化代码:
import streamlit as st
if not st.user.is_logged_in:
st.button("Log in with Google", on_click=st.login)
st.stop()
st.button("Log out", on_click=st.logout)
st.markdown(f"Welcome! {st.user.name}")
4. 示例 2:使用多个 OIDC 提供者
编辑配置文件 .streamlit/secrets.toml:
[auth]
redirect_uri = "http://localhost:8501/oauth2callback"
cookie_secret = "xxx"
[auth.google]
client_id = "xxx"
client_secret = "xxx"
server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration"
[auth.microsoft]
client_id = "xxx"
client_secret = "xxx"
server_metadata_url = "https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration"
创建登录流程:
import streamlit as st
if not st.user.is_logged_in:
if st.button("Log in with Google"):
st.login("google")
if st.button("Log in with Microsoft"):
st.login("microsoft")
st.stop()
if st.button("Log out"):
st.logout()
st.markdown(f"Welcome! {st.user.name}")
改进:使用回调函数简化代码:
import streamlit as st
if not st.user.is_logged_in:
st.button("Log in with Google", on_click=st.login, args=["google"])
st.button("Log in with Microsoft", on_click=st.login, args=["microsoft"])
st.stop()
st.button("Log out", on_click=st.logout)
st.markdown(f"Welcome! {st.user.name}")
API 参考
st.write 和魔法方法
| 功能 | 函数签名 | 函数用途 | 主要参数 | 参数作用 | 代码示例 |
|---|---|---|---|---|---|
st.write | st.write(*args, unsafe_allow_html=False, **kwargs) | Streamlit 的通用写入函数,能自动识别输入内容类型(文本、DataFrame、图表、字典等),并选择最合适的显示方式(如 st.markdown、st.dataframe 等)。 | *args: 可变数量的参数unsafe_allow_html: 是否允许渲染 HTML**kwargs: 传递给底层组件的额外参数 | *args: 接收任意数量和类型的对象,可一次写入多个内容unsafe_allow_html=True 时,支持渲染 HTML 标签(有 XSS 风险,需谨慎)**kwargs 可用于控制图表宽度等(如 use_container_width=True) | st.write("Hello, 世界!")st.write(pd.DataFrame({"A": [1, 2], "B": [3, 4]}))st.write("这是 **粗体** 文本")st.write("<span style='color:red'>红色文字</span>", unsafe_allow_html=True) |
| 魔法方法 | 无函数签名。直接在脚本中书写表达式或字符串字面量即可。 | 一种语法糖机制,允许开发者省略 st.write() 或 st.markdown() 调用,直接将变量或字符串渲染到页面上,使代码更简洁。 | 无参数。直接使用变量名或字符串。 | 单独一行的变量(如 df)→ 自动调用 st.write(df)单独一行的字符串(如 "## 标题")→ 自动调用 st.markdown(...)支持 f-string、三引号多行文本等 | df"## 今日天气""""这是一个多行文本示例。"""f"北京当前温度:{df['温度'][0]}°C" |
文本元素
| 功能 | 函数签名 | 函数用途 | 主要参数 | 参数作用 | 代码示例 |
|---|---|---|---|---|---|
st.text | st.text(body) | 显示固定宽度、预格式化文本,使用 <pre> 标签,保留空格和换行,不支持 Markdown。 | body (str): 要显示的纯文本内容 | body: 输入的字符串将原样显示,适合展示代码片段或日志输出 | st.text("Hello,\nWorld!") |
st.markdown | st.markdown(body, unsafe_allow_html=False) | 渲染 Markdown 格式文本,支持标题、列表、粗体、斜体、链接、图片等。支持传入生成器实现流式输出(≥1.27)。 | body (str 或 generator): Markdown 文本或生成器unsafe_allow_html (bool): 是否允许渲染 HTML | body: 支持标准 Markdown 语法unsafe_allow_html=True 可渲染 HTML,但存在安全风险 | st.markdown("# 主标题")st.markdown("**粗体** 和 *斜体*")st.markdown("- 项目1\n- 项目2") |
st.write | st.write(*args, unsafe_allow_html=False, **kwargs) | 通用写入函数,自动推断内容类型。对于字符串,默认按 Markdown 渲染(部分 HTML 需开启 unsafe_allow_html)。 | *args: 任意数量的对象unsafe_allow_html (bool)**kwargs: 传递给底层组件的参数 | 自动识别 DataFrame、图表、数字、字符串等 字符串行为类似 st.markdown是”魔法方法”的底层实现 | st.write("## 这是标题(Markdown)")st.write(42)st.write({"key": "value"}) |
st.caption | st.caption(body, unsafe_allow_html=False) | 显示小号灰色文本,常用于图片说明、数据来源、注释等次要信息。支持流式输出。 | body (str 或 generator): 要显示的文本unsafe_allow_html (bool) | 文本样式为较小字号、浅灰色 语义上表示”说明文字” | st.caption("图1:示例图片") |
st.code | st.code(body, language="python") | 显示代码块,带语法高亮和复制按钮。默认语言为 Python。 | body (str): 代码字符串language (str): 编程语言(如 "python", "js", "sql", "none") | language="none" 可关闭语法高亮自动添加复制到剪贴板功能 | st.code('print("Hello World")', language='python')st.code('SELECT * FROM users;', language='sql') |
st.latex | st.latex(body) | 渲染 LaTeX 数学公式,使用 MathJax,支持行内和块级公式。 | body (str): LaTeX 表达式 | 显示美观的数学符号和公式 常用于科学计算、教学应用 | st.latex(r"E = mc^2")st.latex(r"\int_a^b f(x)dx") |
st.divider | st.divider() | 插入一条水平分隔线,用于视觉上分隔不同内容区块。 | 无 | 简洁的 UI 分隔符 提升页面结构清晰度 | st.divider() |
| 魔法方法 | 无函数签名 | 语法糖:直接在脚本中写变量或字符串,自动调用 st.write 或 st.markdown。 | 无 | df → st.write(df)"## 标题" → st.markdown("## 标题") | df"## 使用魔法方法" |
推荐使用顺序:
- 一般文本/动态内容 →
st.markdown(支持流式) - 代码展示 →
st.code - 注释/说明 →
st.caption - 数学公式 →
st.latex - 分隔内容 →
st.divider() - 快速原型 →
st.write或 魔法方法
数据元素
| 功能 | 函数签名 | 函数用途 | 主要参数 | 参数作用 | 代码示例 |
|---|---|---|---|---|---|
st.dataframe | st.dataframe(data=None, width=None, height=None, **kwargs) | 显示可交互的只读表格,支持排序、列宽调整、复制等。自动推断数据类型并高亮。 | data: DataFrame、Series、pandas 兼容对象或 2D 数组width, height: 表格宽高(像素)**kwargs: 传递给底层组件 | 支持 pandas、PyArrow、NumPy 等格式 默认可排序,但不可编辑单元格 适合查看和分析数据 | st.dataframe(df, width=500, height=200) |
st.table | st.table(data=None) | 显示静态、不可交互的表格,一次性渲染所有数据,适合小数据集”快照式”展示。 | data: DataFrame、Series 或 2D 数据结构 | 渲染为固定 HTML 表格 不支持排序、滚动或编辑 适用于强调数据完整性或打印样式 | st.table(df) |
st.data_editor | st.data_editor(data, width=None, height=None, num_rows="dynamic", use_container_width=False, disabled=False, column_config=None, key=None, on_change=None, args=None, kwargs=None) | 显示可编辑的交互式表格,支持编辑单元格、增删行(num_rows="dynamic")、排序过滤、列配置及回调函数(on_change)。 | data: 输入数据(DataFrame 等)num_rows: "fixed" 或 "dynamic"(允许增删行)column_config: 配置列行为on_change: 数据更改时的回调函数 | num_rows="dynamic" 允许用户添加/删除行column_config 可定制列类型、默认值、验证、URL 转换等返回编辑后的数据,需用 st.session_state 保存状态 | edited_df = st.data_editor(df, num_rows="dynamic", column_config={"姓名": st.column_config.TextColumn("姓名"), "年龄": st.column_config.NumberColumn("年龄", min_value=0, max_value=150)}) |
st.metric | st.metric(label, value, delta=None, delta_color="normal", help=None) | 显示关键指标(KPI),常用于仪表盘,支持数值变化(delta)和颜色提示(增长/下降)。 | label (str): 指标名称value: 当前值delta: 与之前值的差值delta_color: "normal"(增长绿/下降红)、"inverse"、"off" | 视觉突出,适合监控场景help 提供额外解释 | st.metric(label="销售额", value="¥120,000", delta="+12%") |
st.json | st.json(body, expanded=True) | 格式化显示 JSON 数据,带语法高亮、折叠/展开功能,适合查看嵌套结构或 API 响应。 | body: 字典、列表或 JSON 字符串expanded (bool): 是否默认展开所有层级 | 自动美化 JSON 输出expanded=False 可折叠查看大型结构 | st.json(data, expanded=False) |
图表元素
| 功能 | 函数签名 | 函数用途 | 主要参数 | 代码示例 |
|---|---|---|---|---|
st.line_chart | st.line_chart(data=None, *, x=None, y=None, color=None, width=None, height=None, use_container_width=True) | 快速绘制折线图,适用于时间序列或趋势分析。支持自动列选择。 | data: DataFrame、字典或数组x, y: 坐标轴列color: 指定颜色映射列 | st.line_chart(df, x=None, y=['A', 'B']) |
st.area_chart | st.area_chart(data=None, *, x=None, y=None, color=None, stack=True, width=None, height=None, use_container_width=True) | 绘制面积图,用于显示数量随时间累积的变化,支持堆叠(默认)。 | data: 数据源stack: 是否堆叠显示 | st.area_chart(df, y=['A', 'B'], stack=True) |
st.bar_chart | st.bar_chart(data=None, *, x=None, y=None, color=None, horizontal=False, stack=False, width=None, height=None, use_container_width=True) | 绘制柱状图(垂直或水平),用于比较类别间数值大小。 | horizontal: 是否横向显示 | st.bar_chart(df, y='A', color='B') |
st.scatter_chart | st.scatter_chart(data=None, *, x=None, y=None, color=None, size=None, width=None, height=None, use_container_width=True) | 绘制散点图,用于观察两个变量之间的关系或分布模式。 | color: 第三个变量映射颜色size: 第四个变量映射点大小 | st.scatter_chart(df_scatter, x="x", y="y", color="color", size="size") |
st.map | st.map(data=None, *, latitude=None, longitude=None, color=None, size=None, zoom=10, use_container_width=True) | 快速在地图上绘制点数据,基于 Mapbox,适用于地理位置可视化。 | data: 包含经纬度的 DataFramezoom: 初始缩放级别 | st.map(df_map, zoom=12) |
st.pyplot | st.pyplot(fig=None, clear_figure=False, **kwargs) | 显示 Matplotlib 创建的图表。 | fig: matplotlib Figure 对象clear_figure: 是否清空图 | st.pyplot(fig) |
st.altair_chart | st.altair_chart(chart, use_container_width=False, theme="streamlit", **kwargs) | 显示 Altair 创建的交互式图表(基于 Vega-Lite)。 | chart: Altair Chart 对象theme: 主题 | st.altair_chart(c, use_container_width=True) |
st.vega_lite_chart | st.vega_lite_chart(spec, use_container_width=False, theme="streamlit", **kwargs) | 直接渲染 Vega-Lite JSON 规范的图表,灵活性最高。 | spec: Vega-Lite JSON 规范(字典) | st.vega_lite_chart(spec) |
st.plotly_chart | st.plotly_chart(fig, use_container_width=False, sharing="streamlit", **kwargs) | 显示 Plotly 创建的高度交互式图表(缩放、拖拽、悬停、3D)。 | fig: Plotly Figure 对象 | st.plotly_chart(fig, use_container_width=True) |
st.bokeh_chart | st.bokeh_chart(fig, use_container_width=False) | 显示 Bokeh 创建的交互式图表,适合大型数据集和复杂交互。 | fig: Bokeh Figure 对象 | st.bokeh_chart(bokeh_fig, use_container_width=True) |
st.pydeck_chart | st.pydeck_chart(deckgl_json, use_container_width=False) | 显示 PyDeck 创建的 3D 地理空间可视化(如热力图、路径图、3D 建筑)。 | deckgl_json: PyDeck Deck 对象或 JSON 规范 | st.pydeck_chart(pdk.Deck(layers=[layer])) |
st.graphviz_chart | st.graphviz_chart(spec, format=None, engine=None, encoding='utf-8') | 显示 Graphviz 创建的有向图/流程图/树结构。 | spec: DOT 语言字符串或字典 | st.graphviz_chart(dot) |
使用建议与说明:
| 图表类型 | 推荐场景 | 性能提示 |
|---|---|---|
st.line_chart, st.bar_chart 等 | 快速原型、简单趋势展示 | 轻量,无需导入额外库 |
st.pyplot | Matplotlib 用户,已有代码 | 注意 fig 复用和 clear_figure |
st.plotly_chart | 高交互仪表盘、金融、3D 图 | 交互最强,但包较大 |
st.altair_chart | 声明式语法、统计图表 | 语法优雅,适合复杂编码 |
st.pydeck_chart | 地理空间、3D 可视化 | 处理大规模地理数据能力强 |
st.map | 快速展示点位置 | 简单快捷,但定制性低 |
通用提示:
- 所有图表默认支持
use_container_width=True以适配容器宽度。 - 对于大型数据集,建议在后端做聚合或采样,避免前端卡顿。
- 可结合
st.expander或st.tabs组织多个图表。
输入控件
| 功能 | 函数签名 | 函数用途 | 主要参数 | 代码示例 |
|---|---|---|---|---|
st.text_input | st.text_input(label, value="", max_chars=None, key=None, type="default", help=None, on_change=None, placeholder=None, disabled=False, label_visibility="visible") | 创建单行文本输入框,用于接收用户输入的字符串。 | type: "default" 或 "password"(隐藏输入)placeholder: 占位提示文本 | name = st.text_input("姓名", placeholder="请输入姓名") |
st.number_input | st.number_input(label, min_value=None, max_value=None, value=None, step=None, format=None, key=None, help=None, on_change=None, disabled=False, label_visibility="visible") | 创建数字输入框,支持整数和浮点数,可设置范围、步长。 | min_value, max_value: 数值范围step: 增减步长 | age = st.number_input("年龄", min_value=0, max_value=120, value=25, step=1) |
st.text_area | st.text_area(label, value="", height=None, max_chars=None, key=None, help=None, on_change=None, placeholder=None, disabled=False, label_visibility="visible") | 创建多行文本输入框,适合长文本输入(如评论、代码、说明)。 | height: 组件高度(像素)placeholder: 占位符 | feedback = st.text_area("意见反馈", placeholder="请写下您的建议...") |
st.checkbox | st.checkbox(label, value=False, key=None, help=None, on_change=None, disabled=False, label_visibility="visible") | 创建复选框,用于布尔值选择(开/关、是/否)。 | value: 默认是否选中 | if st.checkbox("显示详细信息"): st.write("详细信息已展开...") |
st.radio | st.radio(label, options, index=0, format_func=str, key=None, help=None, horizontal=False, disabled=False, label_visibility="visible") | 创建单选按钮组,从多个选项中选择一项。 | options: 选项列表horizontal: 是否横向排列 | choice = st.radio("选择城市", ["北京", "上海", "广州"], index=1, horizontal=True) |
st.selectbox | st.selectbox(label, options, index=0, format_func=str, key=None, help=None, disabled=False, label_visibility="visible", placeholder=None) | 创建下拉选择框,从多个选项中选择一项,节省空间。 | options: 选项列表placeholder: 未选择时的提示 | color = st.selectbox("选择颜色", ["红色", "绿色", "蓝色"], placeholder="请选择...") |
st.multiselect | st.multiselect(label, options, default=None, format_func=str, key=None, help=None, disabled=False, label_visibility="visible", placeholder=None) | 创建多选框下拉列表,可选择多个选项,返回列表。 | options: 所有可选项default: 默认选中项(列表) | fruits = st.multiselect("选择水果", ["苹果", "香蕉", "橙子"], default=["苹果"]) |
st.slider | st.slider(label, min_value=None, max_value=None, value=None, step=None, format=None, key=None, help=None, on_change=None, disabled=False, label_visibility="visible") | 创建滑块控件,用于在范围内选择数值或日期。支持单值、范围选择。 | min_value, max_value: 范围value: 默认值,可为单值或元组 | score = st.slider("评分", 0.0, 10.0, 5.0, 0.5)age_range = st.slider("年龄区间", 0, 100, (25, 40)) |
st.select_slider | st.select_slider(label, options, value=None, format_func=str, key=None, help=None, disabled=False, label_visibility="visible") | 创建基于选项的滑块,从预定义的有序选项列表中选择一项或一个范围。 | options: 有序选项列表value: 默认值,可为单值或元组(范围) | priority = st.select_slider("优先级", options=["低", "中", "高"], value="中") |
st.color_picker | st.color_picker(label, value=None, key=None, help=None, on_change=None, disabled=False, label_visibility="visible") | 创建颜色选择器,返回十六进制颜色代码(如 #FF0000)。 | value: 默认颜色 | color = st.color_picker("选择主题色", "#00f900") |
st.button | st.button(label, key=None, help=None, on_click=None, type="secondary", disabled=False, use_container_width=False) | 创建按钮,点击后返回 True 一次(可用于触发操作)。 | type: "primary"(主按钮)或 "secondary" | if st.button("点击我"): st.write("按钮被点击了!") |
st.download_button | st.download_button(label, data, file_name=None, mime=None, key=None, help=None, on_click=None, disabled=False, use_container_width=False) | 创建下载按钮,允许用户下载数据、文件或生成的内容。 | data: 要下载的数据file_name: 下载的文件名mime: MIME 类型 | st.download_button(label="下载 CSV", data=csv, file_name="data.csv", mime="text/csv") |
st.file_uploader | st.file_uploader(label, type=None, accept_multiple_files=False, key=None, help=None, on_change=None, disabled=False, label_visibility="visible") | 创建文件上传控件,允许用户上传本地文件。 | type: 允许的文件类型accept_multiple_files: 是否允许多文件 | uploaded_file = st.file_uploader("上传 CSV 文件", type="csv") |
st.camera_input | st.camera_input(label, key=None, help=None, on_change=None, disabled=False, label_visibility="visible") | 创建摄像头输入,允许用户拍照上传图像。 | 返回 UploadedFile 对象 | camera_photo = st.camera_input("拍照上传") |
st.date_input | st.date_input(label, value=None, min_value=None, max_value=None, key=None, help=None, on_change=None, disabled=False, label_visibility="visible", format="YYYY/MM/DD") | 创建日期选择器,用于选择单个日期或日期范围。 | value: 默认值,可为 date 对象或 "today" | selected_date = st.date_input("选择日期", value="today") |
st.time_input | st.time_input(label, value=None, key=None, help=None, on_change=None, disabled=False, label_visibility="visible", step=60) | 创建时间选择器,用于选择具体时间点。 | value: 默认时间step: 选择步长(秒) | meeting_time = st.time_input("会议时间", value="now") |
通用说明:
key参数:所有控件都支持key,用于在st.session_state中唯一标识该控件,实现状态持久化和跨回调访问。on_change回调:几乎所有输入控件都支持on_change,在值改变时触发函数,适合做实时验证、联动更新。disabled:可禁用控件,使其不可交互。label_visibility:控制标签是否显示、隐藏或折叠。- 重运行机制:Streamlit 应用在用户交互后会重新运行整个脚本,因此控件值需通过变量捕获并在后续逻辑中使用。
媒体元素
| 功能 | 函数签名 | 函数用途 | 主要参数 | 代码示例 |
|---|---|---|---|---|
st.image | st.image(image, caption=None, width=None, use_column_width=None, clamp=False, channels="RGB", output_format="auto") | 显示图像(本地文件、URL、PIL 图像、NumPy 数组、字节数据等)。 | image: 图像源caption: 说明文字width: 显示宽度(像素)channels: "RGB" 或 "BGR" | st.image("logo.png", caption="公司 Logo", width=200)st.image(img_array, channels="RGB") |
st.audio | st.audio(data, format="audio/wav", start_time=0, sample_rate=None, loop=False, autoplay=False) | 播放音频文件,显示音频播放器控件。 | data: 音频数据(路径、URL、字节)format: MIME 类型start_time: 初始播放时间(秒) | st.audio("sample.mp3", format="audio/mp3", start_time=0) |
st.video | st.video(data, format="video/mp4", start_time=0, subtitles=None, loop=False, autoplay=False, muted=False) | 播放视频文件,显示视频播放器。 | data: 视频源format: MIME 类型subtitles: 字幕文件 URLstart_time: 起始播放时间(秒) | st.video("demo.mp4", format="video/mp4", start_time=10) |
说明与建议:
- 本地文件路径(相对或绝对)
- 网络 URL(HTTP/HTTPS)
- 字节数据(BytesIO、bytearray 等),适合动态生成内容
- 文件对象(
open("file.mp3", "rb"))
st.image 特别说明:
- GIF 支持:可播放动画 GIF。
- 多图像输入:
image参数可接受列表,一次显示多张图像。 - PIL/Pillow 集成:可直接传入
PIL.Image对象。 - OpenCV 兼容:OpenCV 默认使用 BGR 通道,需设置
channels="BGR"。
st.audio 注意事项:
- 浏览器安全策略通常禁止自动播放带声音的音频,建议结合
muted=True或用户交互后播放。 - 原始 PCM 数据需提供
sample_rate参数。 - 支持的格式取决于浏览器,MP3 和 WAV 兼容性最好。
st.video 注意事项:
video/mp4(H.264 + AAC):最推荐,所有现代浏览器支持。video/webm(VP8/VP9 + Vorbis/Opus):开源格式。- 大视频文件建议压缩或提供流式服务。
subtitles参数用于提供外挂字幕(WebVTT 格式)。
布局与容器
| 功能 | 函数签名 | 函数用途 | 主要参数 | 代码示例 |
|---|---|---|---|---|
st.sidebar | 不直接调用,通过向其中添加其他组件来使用(如 st.sidebar.button()) | 创建侧边栏,用于放置导航或控制选项。 | 无需特定参数,直接在侧边栏中添加组件即可。 | if st.sidebar.button('点击我'): st.write("按钮被点击了!") |
st.columns | columns = st.columns(n, gap="small") | 创建并返回一个包含 n 个列的列表,用于水平布局。 | n: 列的数量。gap: 列间距("small", "medium", "large")。 | col1, col2, col3 = st.columns(3) |
st.expander | with st.expander(label, expanded=False): | 创建一个可折叠的容器,用户可以选择展开或收起以查看/隐藏内容。 | label: 展开器标题。expanded: 初始化状态是否展开。 | with st.expander("更多详情"): st.write("更多细节") |
st.container | with st.container(): | 创建一个容器,在其中可以放置其他组件,但不改变页面布局。 | 无特殊参数,作为上下文管理器使用。 | with st.container(): st.write("容器内的文本") |
st.empty | placeholder = st.empty() | 创建一个占位符,允许稍后动态更新其内容。 | 无特殊参数,但需结合后续的 .write()、.image() 等方法使用。 | placeholder = st.empty()placeholder.write(f"计数: {i}") |
聊天元素
| 功能 | 函数签名 | 函数用途 | 主要参数 |
|---|---|---|---|
st.chat_message | st.chat_message(name, avatar=None, *, avatar_style="circle", type="left") | 创建一个聊天消息容器,用于包裹用户或 AI 的消息内容(文本、图像、图表等)。 | name: 消息发送者名称(如 "user" 或 "assistant")avatar: 头像(URL、本地路径或单字符)type: 消息方向("left" 左对齐,"right" 右对齐) |
st.chat_input | st.chat_input(placeholder="Your message", *, max_chars=500, disabled=False, key=None) | 创建一个聊天输入框,用于接收用户的文本输入,通常位于聊天界面底部。 | placeholder: 输入框提示文字max_chars: 最大输入字符数disabled: 是否禁用输入框 |
典型聊天应用结构(结合 st.session_state):
import streamlit as st
# 初始化对话历史
if "messages" not in st.session_state:
st.session_state.messages = [
{"role": "assistant", "content": "你好!我是你的AI助手,有什么可以帮助你?"}
]
# 显示历史消息
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.write(message["content"])
# 处理用户输入
if prompt := st.chat_input("请输入你的问题"):
# 添加用户消息到历史
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.write(prompt)
# 模拟 AI 回复(实际可调用 LLM API)
response = f"你问了:{prompt}。这是一个模拟回复。"
# 添加 AI 消息到历史
st.session_state.messages.append({"role": "assistant", "content": response})
with st.chat_message("assistant"):
st.write(response)
流式输出示例:
def simulate_streaming_response(prompt):
response = f"关于 '{prompt}',我正在思考..."
for word in response.split():
yield word + " "
time.sleep(0.1)
if prompt := st.chat_input("提问"):
st.session_state.messages.append({"role": "user", "content": prompt})
st.chat_message("user").write(prompt)
with st.chat_message("assistant"):
response = st.write_stream(simulate_streaming_response(prompt))
st.session_state.messages.append({"role": "assistant", "content": response})
状态元素
| 功能 | 函数签名 / 语法 | 函数用途 | 主要参数 / 属性 |
|---|---|---|---|
st.session_state | st.session_state.key_name 或 st.session_state["key_name"] | 核心状态管理对象,用于在多次脚本重运行之间持久化变量值,实现用户交互状态记忆。 | 无直接参数,但通过 key 与控件绑定支持属性访问( .)和字典访问([])可存储任意 Python 对象 |
key 参数 | st.widget(..., key="my_input") | 将控件的值自动绑定到 st.session_state 中,实现值的自动持久化和访问。 | key: 字符串,作为 st.session_state 中的键名 |
on_change 回调 | st.widget(..., on_change=my_callback, args=None, kwargs=None) | 在控件值改变时触发的回调函数,常用于状态更新、验证或联动逻辑。 | on_change: 值改变时调用的函数args, kwargs: 传递给回调函数的参数 |
st.form | with st.form(key, clear_on_submit=False, border=True): | 创建表单容器,实现批量提交和状态暂存。表单内控件值在提交前不触发重运行,提交后才统一更新 session_state。 | key: 表单唯一标识clear_on_submit: 提交后是否清空表单border: 是否显示边框 |
带状态的登录表单示例:
import streamlit as st
# 初始化登录状态
if 'logged_in' not in st.session_state:
st.session_state.logged_in = False
if not st.session_state.logged_in:
st.subheader("登录")
with st.form("login_form"):
username = st.text_input("用户名", key="username")
password = st.text_input("密码", type="password", key="password")
submit = st.form_submit_button("登录")
if submit:
if username == "admin" and password == "123456":
st.session_state.logged_in = True
st.rerun()
else:
st.error("用户名或密码错误")
else:
st.write(f"欢迎,{st.session_state.username}!")
if st.button("登出"):
st.session_state.logged_in = False
st.rerun()
st.session_state 使用最佳实践:
| 场景 | 方法 |
|---|---|
| 初始化状态 | 使用 if 'key' not in st.session_state: 检查并初始化 |
| 读取控件值 | 优先使用 st.session_state[key](尤其在回调中) |
| 更新控件值 | 直接赋值 st.session_state[key] = value,UI 会自动同步 |
| 避免重复初始化 | 将初始化逻辑放在脚本最前面,防止每次重运行都重置 |
| 存储复杂对象 | 可存储 DataFrame、模型、配置字典等,但注意内存使用 |
用户认证
st.login()
安装前置依赖:
pip install streamlit[auth]
示例 1:使用 Google 的 OIDC
编辑文件 .streamlit/secrets.toml:
[auth]
redirect_uri = "http://localhost:8501/oauth2callback"
cookie_secret = "xxx"
client_id = "xxx"
client_secret = "xxx"
server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration"
代码:
import streamlit as st
if not st.user.is_logged_in:
if st.button("Log in"):
st.login()
else:
if st.button("Log out"):
st.logout()
st.write(f"Hello, {st.user.name}!")
示例 2:使用指定的 OIDC
编辑文件 .streamlit/secrets.toml:
[auth]
redirect_uri = "http://localhost:8501/oauth2callback"
cookie_secret = "xxx"
[auth.microsoft]
client_id = "xxx"
client_secret = "xxx"
server_metadata_url = "https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration"
代码:
import streamlit as st
if not st.user.is_logged_in:
st.login("microsoft")
else:
st.write(f"Hello, {st.user.name}!")
示例 3:使用多个 OIDC
[auth]
redirect_uri = "http://localhost:8501/oauth2callback"
cookie_secret = "xxx"
[auth.microsoft]
client_id = "xxx"
client_secret = "xxx"
server_metadata_url = "https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration"
[auth.okta]
client_id = "xxx"
client_secret = "xxx"
server_metadata_url = "https://{subdomain}.okta.com/.well-known/openid-configuration"
import streamlit as st
if not st.user.is_logged_in:
st.header("Log in:")
if st.button("Microsoft"):
st.login("microsoft")
if st.button("Okta"):
st.login("okta")
else:
if st.button("Log out"):
st.logout()
st.write(f"Hello, {st.user.name}!")
st.logout()
import streamlit as st
if not st.user.is_logged_in:
if st.button("Log in"):
st.login()
else:
if st.button("Log out"):
st.logout()
st.write(f"Hello, {st.user.name}!")
st.user
Google 身份令牌示例:
import streamlit as st
if st.user.is_logged_in:
st.write(st.user)
# 返回包含 is_logged_in, iss, email, name, picture 等字段的字典
Microsoft 身份令牌示例:
if st.user.is_logged_in:
st.write(st.user)
# 返回包含 is_logged_in, name, preferred_username, email 等字段的字典
st.user.to_dict():获取用户信息作为字典。
导航页面
| 功能 | 函数签名 | 函数用途 | 主要参数 |
|---|---|---|---|
st.navigation | st.navigation(pages, *, initial_page=None) | 定义整个应用的导航结构,返回一个 Navigation 对象用于运行应用。 | pages: 页面列表(st.Page 对象)initial_page: 初始加载页面(可选) |
st.Page | st.Page(path_or_callable, *, name=None, title=None, icon=None, url_path=None) | 定义一个页面,可指向一个 .py 文件或一个 Python 函数。 | path_or_callable: 页面路径或可调用函数name: 导航栏显示名称icon: 导航项前图标url_path: 自定义 URL 路径 |
st.page_link | st.page_link(page, *, label=None, icon=None) | 创建一个可点击的页面链接按钮,点击后跳转到指定页面。 | page: st.Page 对象或 URL 字符串label: 按钮显示文本(可选)icon: 按钮前图标 |
st.switch_page | st.switch_page(page) | 立即跳转到另一个页面(类似重定向),执行后立即终止当前脚本并加载目标页面。 | page: st.Page 对象或页面文件路径(字符串) |
页面跳转方式对比:
| 方式 | 触发方式 | 是否立即跳转 | 适用场景 |
|---|---|---|---|
st.page_link | 用户点击按钮 | 是 | 页面内导航按钮 |
st.switch_page | 代码执行到该行 | 是 | 登录后跳转、条件重定向 |
| 浏览器导航栏 | 用户手动点击 | 是 | 正常浏览 |
| 侧边栏自动导航 | 用户点击侧边栏 | 是 | 默认行为 |
执行流程
| 功能 | 函数签名 / 语法 | 函数用途 |
|---|---|---|
| 脚本重运行机制 | 无函数签名,为 Streamlit 核心行为 | 每次用户交互都会导致整个 Python 脚本从头开始重新执行。 |
st.rerun() | st.rerun() | 立即重新运行当前脚本,常用于在程序中主动触发重运行。 |
st.stop() | st.stop() | 立即停止脚本执行,防止后续代码运行。常用于条件拦截。 |
st.form / st.form_submit_button | with st.form(key): / submitted = st.form_submit_button("提交") | 创建表单容器,实现”暂存-提交”模式,延迟重运行直到提交。 |
st.experimental_get_query_params() / st.experimental_set_query_params() | params = st.experimental_get_query_params() / st.experimental_set_query_params(**params) | 获取和设置 URL 查询参数,可用于保存状态、实现页面跳转传参、深链接。 |
st.switch_page() | st.switch_page(page) | 立即跳转到另一个页面,终止当前脚本执行。 |
执行流程核心要点总结:
| 机制 | 特点 | 用途 |
|---|---|---|
| 全脚本重运行 | 每次交互 → 整个 .py 文件从头执行 | 简化状态模型 |
st.rerun() | 主动触发一次重运行 | 状态更新后刷新 UI |
st.stop() | 立即终止当前运行 | 条件拦截、权限验证 |
st.form | 延迟重运行,批量提交 | 优化用户体验 |
st.experimental_set_query_params() | 修改 URL 并触发重运行 | 状态持久化、深链接 |
st.switch_page() | 跳转到其他页面并终止当前脚本 | 多页面应用重定向 |
缓存与状态
| 功能 | 函数签名 / 语法 | 函数用途 | 主要参数 |
|---|---|---|---|
st.cache_data | @st.cache_data 或 @st.cache_data(ttl=3600, max_entries=100, show_spinner=True) | 缓存耗时计算的结果(如数据处理、API 调用),避免重复执行。适用于不可变数据(如 DataFrame、字典、数字)。 | ttl: 缓存生存时间(秒)max_entries: 最多缓存条目数show_spinner: 是否显示加载动画 |
st.cache_resource | @st.cache_resource 或 @st.cache_resource(ttl=3600, max_entries=20) | 缓存全局资源对象(如数据库连接、机器学习模型、API 客户端),这些对象昂贵且可共享于所有用户会话。 | ttl: 资源存活时间(秒)max_entries: 最大缓存资源数show_spinner: 是否显示加载提示 |
st.session_state | st.session_state.key = value 或 st.session_state["key"] = value | 持久化用户会话状态,在单个用户多次脚本重运行之间保持变量值。每个用户有独立的 session_state。 | 无参数,为字典式对象 支持属性和键访问 |
st.query_params | value = st.query_params[key] / st.query_params[key] = value / del st.query_params[key] / st.query_params.clear() | 读写 URL 查询参数(?key=value),实现深链接、状态分享、页面间传参。 | 支持字符串、数字、列表等类型 |
st.context.cookies | from streamlit import context / cookies = context.cookies | (实验性)读取浏览器发送的 Cookies。 | 只读属性,返回 dict |
st.context.headers | from streamlit import context / headers = context.headers | (实验性)读取 HTTP 请求头(如 User-Agent, Authorization)。 | 只读,返回请求头字典 |
核心概念与使用场景对比:
| 机制 | 存储位置 | 共享范围 | 生命周期 | 是否可写 | 典型用途 |
|---|---|---|---|---|---|
st.cache_data | 内存(服务器) | 所有用户共享缓存键 | 可配置(ttl)或手动清除 | 是 | 缓存计算结果、API 响应 |
st.cache_resource | 内存(服务器) | 所有用户共享同一对象 | 应用运行期间,或 ttl 过期 | 是 | 缓存模型、数据库连接 |
st.session_state | 内存(服务器) | 每个用户独立 | 用户会话期间 | 是 | 用户状态、交互逻辑 |
st.query_params | URL(浏览器) | 每个用户独立(通过 URL) | 手动修改或清除 | 是 | 深链接、状态分享、分页 |
st.context.cookies | 浏览器(客户端) | 每个用户 | 由 Cookie 设置决定 | 否(只读) | 读取认证 token、偏好 |
st.context.headers | HTTP 请求 | 每个请求 | 单次请求 | 否(只读) | 获取 Authorization、User-Agent |
连接与密钥
| 功能 | 函数签名 / 语法 | 函数用途 | 主要参数 |
|---|---|---|---|
st.secrets | st.secrets["key"] 或 st.secrets.key.subkey | 安全访问敏感信息(如 API 密钥、数据库密码),内容来自 .streamlit/secrets.toml 文件或环境变量。 | 无函数参数,为类字典对象 支持属性和键访问(嵌套) |
secrets.toml | 文件路径:.streamlit/secrets.toml,格式:TOML | 本地密钥配置文件,用于在开发环境中定义 st.secrets 的值。 | 无参数,为配置文件 必须放在 .streamlit/ 目录下必须添加到 .gitignore |
st.connection | st.connection(name, type=None, **kwargs) | 创建并缓存一个数据连接实例,用于安全、高效地访问数据库或外部服务。 | name: 连接名称type: 连接类型(如 "sql", "snowflake")或类**kwargs: 传递给连接类的参数 |
SQLConnection | st.connection(..., type="sql") | 通用 SQL 数据库连接,支持 SQLite、PostgreSQL、MySQL、BigQuery 等。 | url: 数据库连接字符串dialect: SQL 方言 |
SnowflakeConnection | st.connection("sf", type="snowflake", ...) | 专为 Snowflake 数据仓库优化的连接。 | account, user, password, database, schema 等 |
BaseConnection | class MyConnection(BaseConnection[ClientType]): ... | (高级)自定义连接类的基类,用于扩展 st.connection 支持新服务。 | 需实现 ._connect() 方法返回客户端实例 |
SnowparkConnection | st.connection("snowpark", type="snowpark", ...) | 连接到 Snowflake Snowpark(DataFrame API),用于大规模数据处理。 | 参数同 SnowflakeConnection |
连接类型对比:
| 连接类型 | 适用场景 | 返回对象 | 查询方法 |
|---|---|---|---|
"sql" | 通用 SQL DB(SQLite, PG, MySQL) | SQLConnection | .query() |
"snowflake" | Snowflake 查询 | SnowflakeConnection | .query() |
"snowpark" | Snowflake Snowpark(大数据) | SnowparkConnection | .session(Snowpark Session) |
| 自定义类 | REST API、NoSQL、特殊服务 | 自定义客户端 | 自定义方法 |
配置
| 功能 | 函数签名 / 语法 | 函数用途 | 主要参数 |
|---|---|---|---|
config.toml | 文件路径:~/.streamlit/config.toml(全局)或 .streamlit/config.toml(项目级) | 定义 Streamlit 全局或项目级默认配置,影响运行行为、主题、服务器设置等。 | 支持 [server], [client], [theme], [logger] 等 section |
st.get_option() | st.get_option(name) | 获取当前 Streamlit 运行时配置项的值。 | name (str): 配置项的路径,如 "server.port", "theme.base" |
st.set_option() | st.set_option(name, value) | 在运行时动态设置某些可变的配置项(仅限允许运行时修改的选项)。 | name (str): 配置项名称value: 要设置的值 |
st.set_page_config() | st.set_page_config(page_title="My App", page_icon="🦈", layout="wide", initial_sidebar_state="expanded", menu_items={...}) | 配置单个页面的元信息和布局,必须在脚本最开始调用(在任何其他 st. 命令之前)。 | page_title: 浏览器标签页标题page_icon: 标题栏图标layout: "centered" 或 "wide"initial_sidebar_state: 侧边栏初始状态menu_items: 自定义帮助菜单 |
常用配置项:
| 配置 Section | 常见配置项 | 说明 |
|---|---|---|
server | port, address, enableCORS, maxUploadSize | 服务器行为 |
client | caching, spinner, debug | 客户端行为 |
theme | base, primaryColor, backgroundColor, textColor, font | 主题颜色与字体 |
runner | magicEnabled, installTracer | 运行时行为 |
logger | level, file_format, stream_format | 日志配置 |
browser | serverAddress, gatherUsageStats | 浏览器相关设置 |
命令行
| 命令 | 命令签名 / 语法 | 命令用途 | 主要参数 |
|---|---|---|---|
streamlit run | streamlit run [OPTIONS] filename.py [ARGS]... | 运行一个 Streamlit 脚本,启动本地服务器并打开浏览器。 | --server.port: 指定端口(默认 8501)--server.address: 绑定地址--browser.gatherUsageStats=false: 禁用使用统计[ARGS]...: 传递给脚本的自定义参数 |
streamlit config show | streamlit config show | 显示当前所有配置项的值(包括默认值、配置文件值、环境变量覆盖等)。 | 无参数 |
streamlit cache clear | streamlit cache clear | 清除所有缓存数据(@st.cache_data 和 @st.cache_resource)。 | 无参数 |
streamlit docs | streamlit docs | 在浏览器中打开 Streamlit 官方文档。 | 无参数 |
streamlit version | streamlit version | 显示当前安装的 Streamlit 版本。 | 无参数 |
streamlit list-commands | streamlit list-commands | 列出所有可用的 streamlit 命令。 | 无参数 |
streamlit help | streamlit help 或 streamlit help <command> | 显示帮助信息,可查看所有命令或特定命令的用法。 | <command>: 可选,指定子命令 |
命令分类与使用场景:
| 类别 | 命令 | 典型用途 |
|---|---|---|
| 应用运行 | streamlit run | 启动应用,开发调试 |
| 配置管理 | streamlit config show | 调试配置问题,确认设置生效 |
| 缓存管理 | streamlit cache clear | 清除缓存,强制重新加载数据或模型 |
| 文档与帮助 | streamlit docs, streamlit help | 学习 API、查看命令用法 |
| 版本信息 | streamlit version | 检查版本,确保兼容性 |
高级技巧:
使用环境变量设置配置:
# 通过环境变量指定端口
STREAMLIT_SERVER_PORT=9000 streamlit run app.py
# 禁用自动打开浏览器
STREAMLIT_BROWSER_SERVER_ADDRESS=localhost streamlit run app.py
在 Docker 中运行:
CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
调试模式运行:
streamlit run app.py \
--global.developmentMode=true \
--logger.level=debug \
--browser.gatherUsageStats=false
传递自定义参数给脚本:
streamlit run app.py --user=admin --mode=preview
API 参考
st.write 和魔法方法
| 功能 | 函数签名 | 函数用途 | 主要参数 | 参数作用 | 代码示例 |
|---|---|---|---|---|---|
st.write | st.write(*args, unsafe_allow_html=False, **kwargs) | Streamlit 的通用写入函数,能自动识别输入内容类型(文本、DataFrame、图表、字典等),并选择最合适的显示方式(如 st.markdown、st.dataframe 等)。 | *args: 可变数量的参数unsafe_allow_html: 是否允许渲染 HTML**kwargs: 传递给底层组件的额外参数 | *args: 接收任意数量和类型的对象,可一次写入多个内容unsafe_allow_html=True 时,支持渲染 HTML 标签(有 XSS 风险,需谨慎)**kwargs 可用于控制图表宽度等(如 use_container_width=True) | st.write("Hello, 世界!")st.write(pd.DataFrame({"A": [1, 2], "B": [3, 4]}))st.write("这是 **粗体** 文本")st.write("<span style='color:red'>红色文字</span>", unsafe_allow_html=True) |
| 魔法方法 | 无函数签名。直接在脚本中书写表达式或字符串字面量即可。 | 一种语法糖机制,允许开发者省略 st.write() 或 st.markdown() 调用,直接将变量或字符串渲染到页面上,使代码更简洁。 | 无参数。直接使用变量名或字符串。 | 单独一行的变量(如 df)→ 自动调用 st.write(df)单独一行的字符串(如 "## 标题")→ 自动调用 st.markdown(...)支持 f-string、三引号多行文本等 | df"## 今日天气""""这是一个多行文本示例。"""f"北京当前温度:{df['温度'][0]}°C" |
文本元素
| 功能 | 函数签名 | 函数用途 | 主要参数 | 参数作用 | 代码示例 |
|---|---|---|---|---|---|
st.text | st.text(body) | 显示固定宽度、预格式化文本,使用 <pre> 标签,保留空格和换行,不支持 Markdown。 | body (str): 要显示的纯文本内容 | body: 输入的字符串将原样显示,适合展示代码片段或日志输出 | st.text("Hello,\nWorld!") |
st.markdown | st.markdown(body, unsafe_allow_html=False) | 渲染 Markdown 格式文本,支持标题、列表、粗体、斜体、链接、图片等。支持传入生成器实现流式输出(≥1.27)。 | body (str 或 generator): Markdown 文本或生成器unsafe_allow_html (bool): 是否允许渲染 HTML | body: 支持标准 Markdown 语法unsafe_allow_html=True 可渲染 HTML,但存在安全风险 | st.markdown("# 主标题")st.markdown("**粗体** 和 *斜体*")st.markdown("- 项目1\n- 项目2") |
st.write | st.write(*args, unsafe_allow_html=False, **kwargs) | 通用写入函数,自动推断内容类型。对于字符串,默认按 Markdown 渲染(部分 HTML 需开启 unsafe_allow_html)。 | *args: 任意数量的对象unsafe_allow_html (bool)**kwargs: 传递给底层组件的参数 | 自动识别 DataFrame、图表、数字、字符串等 字符串行为类似 st.markdown是”魔法方法”的底层实现 | st.write("## 这是标题(Markdown)")st.write(42)st.write({"key": "value"}) |
st.caption | st.caption(body, unsafe_allow_html=False) | 显示小号灰色文本,常用于图片说明、数据来源、注释等次要信息。支持流式输出。 | body (str 或 generator): 要显示的文本unsafe_allow_html (bool) | 文本样式为较小字号、浅灰色 语义上表示”说明文字” | st.caption("图1:示例图片") |
st.code | st.code(body, language="python") | 显示代码块,带语法高亮和复制按钮。默认语言为 Python。 | body (str): 代码字符串language (str): 编程语言(如 "python", "js", "sql", "none") | language="none" 可关闭语法高亮自动添加复制到剪贴板功能 | st.code('print("Hello World")', language='python')st.code('SELECT * FROM users;', language='sql') |
st.latex | st.latex(body) | 渲染 LaTeX 数学公式,使用 MathJax,支持行内和块级公式。 | body (str): LaTeX 表达式 | 显示美观的数学符号和公式 常用于科学计算、教学应用 | st.latex(r"E = mc^2")st.latex(r"\int_a^b f(x)dx") |
st.divider | st.divider() | 插入一条水平分隔线,用于视觉上分隔不同内容区块。 | 无 | 简洁的 UI 分隔符 提升页面结构清晰度 | st.divider() |
| 魔法方法 | 无函数签名 | 语法糖:直接在脚本中写变量或字符串,自动调用 st.write 或 st.markdown。 | 无 | df → st.write(df)"## 标题" → st.markdown("## 标题") | df"## 使用魔法方法" |
推荐使用顺序:
- 一般文本/动态内容 →
st.markdown(支持流式) - 代码展示 →
st.code - 注释/说明 →
st.caption - 数学公式 →
st.latex - 分隔内容 →
st.divider() - 快速原型 →
st.write或 魔法方法
数据元素
| 功能 | 函数签名 | 函数用途 | 主要参数 | 参数作用 | 代码示例 |
|---|---|---|---|---|---|
st.dataframe | st.dataframe(data=None, width=None, height=None, **kwargs) | 显示可交互的只读表格,支持排序、列宽调整、复制等。自动推断数据类型并高亮。 | data: DataFrame、Series、pandas 兼容对象或 2D 数组width, height: 表格宽高(像素)**kwargs: 传递给底层组件 | 支持 pandas、PyArrow、NumPy 等格式 默认可排序,但不可编辑单元格 适合查看和分析数据 | st.dataframe(df, width=500, height=200) |
st.table | st.table(data=None) | 显示静态、不可交互的表格,一次性渲染所有数据,适合小数据集”快照式”展示。 | data: DataFrame、Series 或 2D 数据结构 | 渲染为固定 HTML 表格 不支持排序、滚动或编辑 适用于强调数据完整性或打印样式 | st.table(df) |
st.data_editor | st.data_editor(data, width=None, height=None, num_rows="dynamic", use_container_width=False, disabled=False, column_config=None, key=None, on_change=None, args=None, kwargs=None) | 显示可编辑的交互式表格,支持编辑单元格、增删行(num_rows="dynamic")、排序过滤、列配置及回调函数(on_change)。 | data: 输入数据(DataFrame 等)num_rows: "fixed" 或 "dynamic"(允许增删行)column_config: 配置列行为on_change: 数据更改时的回调函数 | num_rows="dynamic" 允许用户添加/删除行column_config 可定制列类型、默认值、验证、URL 转换等返回编辑后的数据,需用 st.session_state 保存状态 | edited_df = st.data_editor(df, num_rows="dynamic", column_config={"姓名": st.column_config.TextColumn("姓名"), "年龄": st.column_config.NumberColumn("年龄", min_value=0, max_value=150)}) |
st.metric | st.metric(label, value, delta=None, delta_color="normal", help=None) | 显示关键指标(KPI),常用于仪表盘,支持数值变化(delta)和颜色提示(增长/下降)。 | label (str): 指标名称value: 当前值delta: 与之前值的差值delta_color: "normal"(增长绿/下降红)、"inverse"、"off" | 视觉突出,适合监控场景help 提供额外解释 | st.metric(label="销售额", value="¥120,000", delta="+12%") |
st.json | st.json(body, expanded=True) | 格式化显示 JSON 数据,带语法高亮、折叠/展开功能,适合查看嵌套结构或 API 响应。 | body: 字典、列表或 JSON 字符串expanded (bool): 是否默认展开所有层级 | 自动美化 JSON 输出expanded=False 可折叠查看大型结构 | st.json(data, expanded=False) |
图表元素
| 功能 | 函数签名 | 函数用途 | 主要参数 | 代码示例 |
|---|---|---|---|---|
st.line_chart | st.line_chart(data=None, *, x=None, y=None, color=None, width=None, height=None, use_container_width=True) | 快速绘制折线图,适用于时间序列或趋势分析。支持自动列选择。 | data: DataFrame、字典或数组x, y: 坐标轴列color: 指定颜色映射列 | st.line_chart(df, x=None, y=['A', 'B']) |
st.area_chart | st.area_chart(data=None, *, x=None, y=None, color=None, stack=True, width=None, height=None, use_container_width=True) | 绘制面积图,用于显示数量随时间累积的变化,支持堆叠(默认)。 | data: 数据源stack: 是否堆叠显示 | st.area_chart(df, y=['A', 'B'], stack=True) |
st.bar_chart | st.bar_chart(data=None, *, x=None, y=None, color=None, horizontal=False, stack=False, width=None, height=None, use_container_width=True) | 绘制柱状图(垂直或水平),用于比较类别间数值大小。 | horizontal: 是否横向显示 | st.bar_chart(df, y='A', color='B') |
st.scatter_chart | st.scatter_chart(data=None, *, x=None, y=None, color=None, size=None, width=None, height=None, use_container_width=True) | 绘制散点图,用于观察两个变量之间的关系或分布模式。 | color: 第三个变量映射颜色size: 第四个变量映射点大小 | st.scatter_chart(df_scatter, x="x", y="y", color="color", size="size") |
st.map | st.map(data=None, *, latitude=None, longitude=None, color=None, size=None, zoom=10, use_container_width=True) | 快速在地图上绘制点数据,基于 Mapbox,适用于地理位置可视化。 | data: 包含经纬度的 DataFramezoom: 初始缩放级别 | st.map(df_map, zoom=12) |
st.pyplot | st.pyplot(fig=None, clear_figure=False, **kwargs) | 显示 Matplotlib 创建的图表。 | fig: matplotlib Figure 对象clear_figure: 是否清空图 | st.pyplot(fig) |
st.altair_chart | st.altair_chart(chart, use_container_width=False, theme="streamlit", **kwargs) | 显示 Altair 创建的交互式图表(基于 Vega-Lite)。 | chart: Altair Chart 对象theme: 主题 | st.altair_chart(c, use_container_width=True) |
st.vega_lite_chart | st.vega_lite_chart(spec, use_container_width=False, theme="streamlit", **kwargs) | 直接渲染 Vega-Lite JSON 规范的图表,灵活性最高。 | spec: Vega-Lite JSON 规范(字典) | st.vega_lite_chart(spec) |
st.plotly_chart | st.plotly_chart(fig, use_container_width=False, sharing="streamlit", **kwargs) | 显示 Plotly 创建的高度交互式图表(缩放、拖拽、悬停、3D)。 | fig: Plotly Figure 对象 | st.plotly_chart(fig, use_container_width=True) |
st.bokeh_chart | st.bokeh_chart(fig, use_container_width=False) | 显示 Bokeh 创建的交互式图表,适合大型数据集和复杂交互。 | fig: Bokeh Figure 对象 | st.bokeh_chart(bokeh_fig, use_container_width=True) |
st.pydeck_chart | st.pydeck_chart(deckgl_json, use_container_width=False) | 显示 PyDeck 创建的 3D 地理空间可视化(如热力图、路径图、3D 建筑)。 | deckgl_json: PyDeck Deck 对象或 JSON 规范 | st.pydeck_chart(pdk.Deck(layers=[layer])) |
st.graphviz_chart | st.graphviz_chart(spec, format=None, engine=None, encoding='utf-8') | 显示 Graphviz 创建的有向图/流程图/树结构。 | spec: DOT 语言字符串或字典 | st.graphviz_chart(dot) |
使用建议与说明:
| 图表类型 | 推荐场景 | 性能提示 |
|---|---|---|
st.line_chart, st.bar_chart 等 | 快速原型、简单趋势展示 | 轻量,无需导入额外库 |
st.pyplot | Matplotlib 用户,已有代码 | 注意 fig 复用和 clear_figure |
st.plotly_chart | 高交互仪表盘、金融、3D 图 | 交互最强,但包较大 |
st.altair_chart | 声明式语法、统计图表 | 语法优雅,适合复杂编码 |
st.pydeck_chart | 地理空间、3D 可视化 | 处理大规模地理数据能力强 |
st.map | 快速展示点位置 | 简单快捷,但定制性低 |
通用提示:
- 所有图表默认支持
use_container_width=True以适配容器宽度。 - 对于大型数据集,建议在后端做聚合或采样,避免前端卡顿。
- 可结合
st.expander或st.tabs组织多个图表。
输入控件
| 功能 | 函数签名 | 函数用途 | 主要参数 | 代码示例 |
|---|---|---|---|---|
st.text_input | st.text_input(label, value="", max_chars=None, key=None, type="default", help=None, on_change=None, placeholder=None, disabled=False, label_visibility="visible") | 创建单行文本输入框,用于接收用户输入的字符串。 | type: "default" 或 "password"(隐藏输入)placeholder: 占位提示文本 | name = st.text_input("姓名", placeholder="请输入姓名") |
st.number_input | st.number_input(label, min_value=None, max_value=None, value=None, step=None, format=None, key=None, help=None, on_change=None, disabled=False, label_visibility="visible") | 创建数字输入框,支持整数和浮点数,可设置范围、步长。 | min_value, max_value: 数值范围step: 增减步长 | age = st.number_input("年龄", min_value=0, max_value=120, value=25, step=1) |
st.text_area | st.text_area(label, value="", height=None, max_chars=None, key=None, help=None, on_change=None, placeholder=None, disabled=False, label_visibility="visible") | 创建多行文本输入框,适合长文本输入(如评论、代码、说明)。 | height: 组件高度(像素)placeholder: 占位符 | feedback = st.text_area("意见反馈", placeholder="请写下您的建议...") |
st.checkbox | st.checkbox(label, value=False, key=None, help=None, on_change=None, disabled=False, label_visibility="visible") | 创建复选框,用于布尔值选择(开/关、是/否)。 | value: 默认是否选中 | if st.checkbox("显示详细信息"): st.write("详细信息已展开...") |
st.radio | st.radio(label, options, index=0, format_func=str, key=None, help=None, horizontal=False, disabled=False, label_visibility="visible") | 创建单选按钮组,从多个选项中选择一项。 | options: 选项列表horizontal: 是否横向排列 | choice = st.radio("选择城市", ["北京", "上海", "广州"], index=1, horizontal=True) |
st.selectbox | st.selectbox(label, options, index=0, format_func=str, key=None, help=None, disabled=False, label_visibility="visible", placeholder=None) | 创建下拉选择框,从多个选项中选择一项,节省空间。 | options: 选项列表placeholder: 未选择时的提示 | color = st.selectbox("选择颜色", ["红色", "绿色", "蓝色"], placeholder="请选择...") |
st.multiselect | st.multiselect(label, options, default=None, format_func=str, key=None, help=None, disabled=False, label_visibility="visible", placeholder=None) | 创建多选框下拉列表,可选择多个选项,返回列表。 | options: 所有可选项default: 默认选中项(列表) | fruits = st.multiselect("选择水果", ["苹果", "香蕉", "橙子"], default=["苹果"]) |
st.slider | st.slider(label, min_value=None, max_value=None, value=None, step=None, format=None, key=None, help=None, on_change=None, disabled=False, label_visibility="visible") | 创建滑块控件,用于在范围内选择数值或日期。支持单值、范围选择。 | min_value, max_value: 范围value: 默认值,可为单值或元组 | score = st.slider("评分", 0.0, 10.0, 5.0, 0.5)age_range = st.slider("年龄区间", 0, 100, (25, 40)) |
st.select_slider | st.select_slider(label, options, value=None, format_func=str, key=None, help=None, disabled=False, label_visibility="visible") | 创建基于选项的滑块,从预定义的有序选项列表中选择一项或一个范围。 | options: 有序选项列表value: 默认值,可为单值或元组(范围) | priority = st.select_slider("优先级", options=["低", "中", "高"], value="中") |
st.color_picker | st.color_picker(label, value=None, key=None, help=None, on_change=None, disabled=False, label_visibility="visible") | 创建颜色选择器,返回十六进制颜色代码(如 #FF0000)。 | value: 默认颜色 | color = st.color_picker("选择主题色", "#00f900") |
st.button | st.button(label, key=None, help=None, on_click=None, type="secondary", disabled=False, use_container_width=False) | 创建按钮,点击后返回 True 一次(可用于触发操作)。 | type: "primary"(主按钮)或 "secondary" | if st.button("点击我"): st.write("按钮被点击了!") |
st.download_button | st.download_button(label, data, file_name=None, mime=None, key=None, help=None, on_click=None, disabled=False, use_container_width=False) | 创建下载按钮,允许用户下载数据、文件或生成的内容。 | data: 要下载的数据file_name: 下载的文件名mime: MIME 类型 | st.download_button(label="下载 CSV", data=csv, file_name="data.csv", mime="text/csv") |
st.file_uploader | st.file_uploader(label, type=None, accept_multiple_files=False, key=None, help=None, on_change=None, disabled=False, label_visibility="visible") | 创建文件上传控件,允许用户上传本地文件。 | type: 允许的文件类型accept_multiple_files: 是否允许多文件 | uploaded_file = st.file_uploader("上传 CSV 文件", type="csv") |
st.camera_input | st.camera_input(label, key=None, help=None, on_change=None, disabled=False, label_visibility="visible") | 创建摄像头输入,允许用户拍照上传图像。 | 返回 UploadedFile 对象 | camera_photo = st.camera_input("拍照上传") |
st.date_input | st.date_input(label, value=None, min_value=None, max_value=None, key=None, help=None, on_change=None, disabled=False, label_visibility="visible", format="YYYY/MM/DD") | 创建日期选择器,用于选择单个日期或日期范围。 | value: 默认值,可为 date 对象或 "today" | selected_date = st.date_input("选择日期", value="today") |
st.time_input | st.time_input(label, value=None, key=None, help=None, on_change=None, disabled=False, label_visibility="visible", step=60) | 创建时间选择器,用于选择具体时间点。 | value: 默认时间step: 选择步长(秒) | meeting_time = st.time_input("会议时间", value="now") |
通用说明:
key参数:所有控件都支持key,用于在st.session_state中唯一标识该控件,实现状态持久化和跨回调访问。on_change回调:几乎所有输入控件都支持on_change,在值改变时触发函数,适合做实时验证、联动更新。disabled:可禁用控件,使其不可交互。label_visibility:控制标签是否显示、隐藏或折叠。- 重运行机制:Streamlit 应用在用户交互后会重新运行整个脚本,因此控件值需通过变量捕获并在后续逻辑中使用。
媒体元素
| 功能 | 函数签名 | 函数用途 | 主要参数 | 代码示例 |
|---|---|---|---|---|
st.image | st.image(image, caption=None, width=None, use_column_width=None, clamp=False, channels="RGB", output_format="auto") | 显示图像(本地文件、URL、PIL 图像、NumPy 数组、字节数据等)。 | image: 图像源caption: 说明文字width: 显示宽度(像素)channels: "RGB" 或 "BGR" | st.image("logo.png", caption="公司 Logo", width=200)st.image(img_array, channels="RGB") |
st.audio | st.audio(data, format="audio/wav", start_time=0, sample_rate=None, loop=False, autoplay=False) | 播放音频文件,显示音频播放器控件。 | data: 音频数据(路径、URL、字节)format: MIME 类型start_time: 初始播放时间(秒) | st.audio("sample.mp3", format="audio/mp3", start_time=0) |
st.video | st.video(data, format="video/mp4", start_time=0, subtitles=None, loop=False, autoplay=False, muted=False) | 播放视频文件,显示视频播放器。 | data: 视频源format: MIME 类型subtitles: 字幕文件 URLstart_time: 起始播放时间(秒) | st.video("demo.mp4", format="video/mp4", start_time=10) |
说明与建议:
- 本地文件路径(相对或绝对)
- 网络 URL(HTTP/HTTPS)
- 字节数据(BytesIO、bytearray 等),适合动态生成内容
- 文件对象(
open("file.mp3", "rb"))
st.image 特别说明:
- GIF 支持:可播放动画 GIF。
- 多图像输入:
image参数可接受列表,一次显示多张图像。 - PIL/Pillow 集成:可直接传入
PIL.Image对象。 - OpenCV 兼容:OpenCV 默认使用 BGR 通道,需设置
channels="BGR"。
st.audio 注意事项:
- 浏览器安全策略通常禁止自动播放带声音的音频,建议结合
muted=True或用户交互后播放。 - 原始 PCM 数据需提供
sample_rate参数。 - 支持的格式取决于浏览器,MP3 和 WAV 兼容性最好。
st.video 注意事项:
video/mp4(H.264 + AAC):最推荐,所有现代浏览器支持。video/webm(VP8/VP9 + Vorbis/Opus):开源格式。- 大视频文件建议压缩或提供流式服务。
subtitles参数用于提供外挂字幕(WebVTT 格式)。
布局与容器
| 功能 | 函数签名 | 函数用途 | 主要参数 | 代码示例 |
|---|---|---|---|---|
st.sidebar | 不直接调用,通过向其中添加其他组件来使用(如 st.sidebar.button()) | 创建侧边栏,用于放置导航或控制选项。 | 无需特定参数,直接在侧边栏中添加组件即可。 | if st.sidebar.button('点击我'): st.write("按钮被点击了!") |
st.columns | columns = st.columns(n, gap="small") | 创建并返回一个包含 n 个列的列表,用于水平布局。 | n: 列的数量。gap: 列间距("small", "medium", "large")。 | col1, col2, col3 = st.columns(3) |
st.expander | with st.expander(label, expanded=False): | 创建一个可折叠的容器,用户可以选择展开或收起以查看/隐藏内容。 | label: 展开器标题。expanded: 初始化状态是否展开。 | with st.expander("更多详情"): st.write("更多细节") |
st.container | with st.container(): | 创建一个容器,在其中可以放置其他组件,但不改变页面布局。 | 无特殊参数,作为上下文管理器使用。 | with st.container(): st.write("容器内的文本") |
st.empty | placeholder = st.empty() | 创建一个占位符,允许稍后动态更新其内容。 | 无特殊参数,但需结合后续的 .write()、.image() 等方法使用。 | placeholder = st.empty()placeholder.write(f"计数: {i}") |
聊天元素
| 功能 | 函数签名 | 函数用途 | 主要参数 |
|---|---|---|---|
st.chat_message | st.chat_message(name, avatar=None, *, avatar_style="circle", type="left") | 创建一个聊天消息容器,用于包裹用户或 AI 的消息内容(文本、图像、图表等)。 | name: 消息发送者名称(如 "user" 或 "assistant")avatar: 头像(URL、本地路径或单字符)type: 消息方向("left" 左对齐,"right" 右对齐) |
st.chat_input | st.chat_input(placeholder="Your message", *, max_chars=500, disabled=False, key=None) | 创建一个聊天输入框,用于接收用户的文本输入,通常位于聊天界面底部。 | placeholder: 输入框提示文字max_chars: 最大输入字符数disabled: 是否禁用输入框 |
典型聊天应用结构(结合 st.session_state):
import streamlit as st
# 初始化对话历史
if "messages" not in st.session_state:
st.session_state.messages = [
{"role": "assistant", "content": "你好!我是你的AI助手,有什么可以帮助你?"}
]
# 显示历史消息
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.write(message["content"])
# 处理用户输入
if prompt := st.chat_input("请输入你的问题"):
# 添加用户消息到历史
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.write(prompt)
# 模拟 AI 回复(实际可调用 LLM API)
response = f"你问了:{prompt}。这是一个模拟回复。"
# 添加 AI 消息到历史
st.session_state.messages.append({"role": "assistant", "content": response})
with st.chat_message("assistant"):
st.write(response)
流式输出示例:
def simulate_streaming_response(prompt):
response = f"关于 '{prompt}',我正在思考..."
for word in response.split():
yield word + " "
time.sleep(0.1)
if prompt := st.chat_input("提问"):
st.session_state.messages.append({"role": "user", "content": prompt})
st.chat_message("user").write(prompt)
with st.chat_message("assistant"):
response = st.write_stream(simulate_streaming_response(prompt))
st.session_state.messages.append({"role": "assistant", "content": response})
状态元素
| 功能 | 函数签名 / 语法 | 函数用途 | 主要参数 / 属性 |
|---|---|---|---|
st.session_state | st.session_state.key_name 或 st.session_state["key_name"] | 核心状态管理对象,用于在多次脚本重运行之间持久化变量值,实现用户交互状态记忆。 | 无直接参数,但通过 key 与控件绑定支持属性访问( .)和字典访问([])可存储任意 Python 对象 |
key 参数 | st.widget(..., key="my_input") | 将控件的值自动绑定到 st.session_state 中,实现值的自动持久化和访问。 | key: 字符串,作为 st.session_state 中的键名 |
on_change 回调 | st.widget(..., on_change=my_callback, args=None, kwargs=None) | 在控件值改变时触发的回调函数,常用于状态更新、验证或联动逻辑。 | on_change: 值改变时调用的函数args, kwargs: 传递给回调函数的参数 |
st.form | with st.form(key, clear_on_submit=False, border=True): | 创建表单容器,实现批量提交和状态暂存。表单内控件值在提交前不触发重运行,提交后才统一更新 session_state。 | key: 表单唯一标识clear_on_submit: 提交后是否清空表单border: 是否显示边框 |
带状态的登录表单示例:
import streamlit as st
# 初始化登录状态
if 'logged_in' not in st.session_state:
st.session_state.logged_in = False
if not st.session_state.logged_in:
st.subheader("登录")
with st.form("login_form"):
username = st.text_input("用户名", key="username")
password = st.text_input("密码", type="password", key="password")
submit = st.form_submit_button("登录")
if submit:
if username == "admin" and password == "123456":
st.session_state.logged_in = True
st.rerun()
else:
st.error("用户名或密码错误")
else:
st.write(f"欢迎,{st.session_state.username}!")
if st.button("登出"):
st.session_state.logged_in = False
st.rerun()
st.session_state 使用最佳实践:
| 场景 | 方法 |
|---|---|
| 初始化状态 | 使用 if 'key' not in st.session_state: 检查并初始化 |
| 读取控件值 | 优先使用 st.session_state[key](尤其在回调中) |
| 更新控件值 | 直接赋值 st.session_state[key] = value,UI 会自动同步 |
| 避免重复初始化 | 将初始化逻辑放在脚本最前面,防止每次重运行都重置 |
| 存储复杂对象 | 可存储 DataFrame、模型、配置字典等,但注意内存使用 |
用户认证
st.login()
安装前置依赖:
pip install streamlit[auth]
示例 1:使用 Google 的 OIDC
编辑文件 .streamlit/secrets.toml:
[auth]
redirect_uri = "http://localhost:8501/oauth2callback"
cookie_secret = "xxx"
client_id = "xxx"
client_secret = "xxx"
server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration"
代码:
import streamlit as st
if not st.user.is_logged_in:
if st.button("Log in"):
st.login()
else:
if st.button("Log out"):
st.logout()
st.write(f"Hello, {st.user.name}!")
示例 2:使用指定的 OIDC
编辑文件 .streamlit/secrets.toml:
[auth]
redirect_uri = "http://localhost:8501/oauth2callback"
cookie_secret = "xxx"
[auth.microsoft]
client_id = "xxx"
client_secret = "xxx"
server_metadata_url = "https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration"
代码:
import streamlit as st
if not st.user.is_logged_in:
st.login("microsoft")
else:
st.write(f"Hello, {st.user.name}!")
示例 3:使用多个 OIDC
[auth]
redirect_uri = "http://localhost:8501/oauth2callback"
cookie_secret = "xxx"
[auth.microsoft]
client_id = "xxx"
client_secret = "xxx"
server_metadata_url = "https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration"
[auth.okta]
client_id = "xxx"
client_secret = "xxx"
server_metadata_url = "https://{subdomain}.okta.com/.well-known/openid-configuration"
import streamlit as st
if not st.user.is_logged_in:
st.header("Log in:")
if st.button("Microsoft"):
st.login("microsoft")
if st.button("Okta"):
st.login("okta")
else:
if st.button("Log out"):
st.logout()
st.write(f"Hello, {st.user.name}!")
st.logout()
import streamlit as st
if not st.user.is_logged_in:
if st.button("Log in"):
st.login()
else:
if st.button("Log out"):
st.logout()
st.write(f"Hello, {st.user.name}!")
st.user
Google 身份令牌示例:
import streamlit as st
if st.user.is_logged_in:
st.write(st.user)
# 返回包含 is_logged_in, iss, email, name, picture 等字段的字典
Microsoft 身份令牌示例:
if st.user.is_logged_in:
st.write(st.user)
# 返回包含 is_logged_in, name, preferred_username, email 等字段的字典
st.user.to_dict():获取用户信息作为字典。
导航页面
| 功能 | 函数签名 | 函数用途 | 主要参数 |
|---|---|---|---|
st.navigation | st.navigation(pages, *, initial_page=None) | 定义整个应用的导航结构,返回一个 Navigation 对象用于运行应用。 | pages: 页面列表(st.Page 对象)initial_page: 初始加载页面(可选) |
st.Page | st.Page(path_or_callable, *, name=None, title=None, icon=None, url_path=None) | 定义一个页面,可指向一个 .py 文件或一个 Python 函数。 | path_or_callable: 页面路径或可调用函数name: 导航栏显示名称icon: 导航项前图标url_path: 自定义 URL 路径 |
st.page_link | st.page_link(page, *, label=None, icon=None) | 创建一个可点击的页面链接按钮,点击后跳转到指定页面。 | page: st.Page 对象或 URL 字符串label: 按钮显示文本(可选)icon: 按钮前图标 |
st.switch_page | st.switch_page(page) | 立即跳转到另一个页面(类似重定向),执行后立即终止当前脚本并加载目标页面。 | page: st.Page 对象或页面文件路径(字符串) |
页面跳转方式对比:
| 方式 | 触发方式 | 是否立即跳转 | 适用场景 |
|---|---|---|---|
st.page_link | 用户点击按钮 | 是 | 页面内导航按钮 |
st.switch_page | 代码执行到该行 | 是 | 登录后跳转、条件重定向 |
| 浏览器导航栏 | 用户手动点击 | 是 | 正常浏览 |
| 侧边栏自动导航 | 用户点击侧边栏 | 是 | 默认行为 |
执行流程
| 功能 | 函数签名 / 语法 | 函数用途 |
|---|---|---|
| 脚本重运行机制 | 无函数签名,为 Streamlit 核心行为 | 每次用户交互都会导致整个 Python 脚本从头开始重新执行。 |
st.rerun() | st.rerun() | 立即重新运行当前脚本,常用于在程序中主动触发重运行。 |
st.stop() | st.stop() | 立即停止脚本执行,防止后续代码运行。常用于条件拦截。 |
st.form / st.form_submit_button | with st.form(key): / submitted = st.form_submit_button("提交") | 创建表单容器,实现”暂存-提交”模式,延迟重运行直到提交。 |
st.experimental_get_query_params() / st.experimental_set_query_params() | params = st.experimental_get_query_params() / st.experimental_set_query_params(**params) | 获取和设置 URL 查询参数,可用于保存状态、实现页面跳转传参、深链接。 |
st.switch_page() | st.switch_page(page) | 立即跳转到另一个页面,终止当前脚本执行。 |
执行流程核心要点总结:
| 机制 | 特点 | 用途 |
|---|---|---|
| 全脚本重运行 | 每次交互 → 整个 .py 文件从头执行 | 简化状态模型 |
st.rerun() | 主动触发一次重运行 | 状态更新后刷新 UI |
st.stop() | 立即终止当前运行 | 条件拦截、权限验证 |
st.form | 延迟重运行,批量提交 | 优化用户体验 |
st.experimental_set_query_params() | 修改 URL 并触发重运行 | 状态持久化、深链接 |
st.switch_page() | 跳转到其他页面并终止当前脚本 | 多页面应用重定向 |
缓存与状态
| 功能 | 函数签名 / 语法 | 函数用途 | 主要参数 |
|---|---|---|---|
st.cache_data | @st.cache_data 或 @st.cache_data(ttl=3600, max_entries=100, show_spinner=True) | 缓存耗时计算的结果(如数据处理、API 调用),避免重复执行。适用于不可变数据(如 DataFrame、字典、数字)。 | ttl: 缓存生存时间(秒)max_entries: 最多缓存条目数show_spinner: 是否显示加载动画 |
st.cache_resource | @st.cache_resource 或 @st.cache_resource(ttl=3600, max_entries=20) | 缓存全局资源对象(如数据库连接、机器学习模型、API 客户端),这些对象昂贵且可共享于所有用户会话。 | ttl: 资源存活时间(秒)max_entries: 最大缓存资源数show_spinner: 是否显示加载提示 |
st.session_state | st.session_state.key = value 或 st.session_state["key"] = value | 持久化用户会话状态,在单个用户多次脚本重运行之间保持变量值。每个用户有独立的 session_state。 | 无参数,为字典式对象 支持属性和键访问 |
st.query_params | value = st.query_params[key] / st.query_params[key] = value / del st.query_params[key] / st.query_params.clear() | 读写 URL 查询参数(?key=value),实现深链接、状态分享、页面间传参。 | 支持字符串、数字、列表等类型 |
st.context.cookies | from streamlit import context / cookies = context.cookies | (实验性)读取浏览器发送的 Cookies。 | 只读属性,返回 dict |
st.context.headers | from streamlit import context / headers = context.headers | (实验性)读取 HTTP 请求头(如 User-Agent, Authorization)。 | 只读,返回请求头字典 |
核心概念与使用场景对比:
| 机制 | 存储位置 | 共享范围 | 生命周期 | 是否可写 | 典型用途 |
|---|---|---|---|---|---|
st.cache_data | 内存(服务器) | 所有用户共享缓存键 | 可配置(ttl)或手动清除 | 是 | 缓存计算结果、API 响应 |
st.cache_resource | 内存(服务器) | 所有用户共享同一对象 | 应用运行期间,或 ttl 过期 | 是 | 缓存模型、数据库连接 |
st.session_state | 内存(服务器) | 每个用户独立 | 用户会话期间 | 是 | 用户状态、交互逻辑 |
st.query_params | URL(浏览器) | 每个用户独立(通过 URL) | 手动修改或清除 | 是 | 深链接、状态分享、分页 |
st.context.cookies | 浏览器(客户端) | 每个用户 | 由 Cookie 设置决定 | 否(只读) | 读取认证 token、偏好 |
st.context.headers | HTTP 请求 | 每个请求 | 单次请求 | 否(只读) | 获取 Authorization、User-Agent |
连接与密钥
| 功能 | 函数签名 / 语法 | 函数用途 | 主要参数 |
|---|---|---|---|
st.secrets | st.secrets["key"] 或 st.secrets.key.subkey | 安全访问敏感信息(如 API 密钥、数据库密码),内容来自 .streamlit/secrets.toml 文件或环境变量。 | 无函数参数,为类字典对象 支持属性和键访问(嵌套) |
secrets.toml | 文件路径:.streamlit/secrets.toml,格式:TOML | 本地密钥配置文件,用于在开发环境中定义 st.secrets 的值。 | 无参数,为配置文件 必须放在 .streamlit/ 目录下必须添加到 .gitignore |
st.connection | st.connection(name, type=None, **kwargs) | 创建并缓存一个数据连接实例,用于安全、高效地访问数据库或外部服务。 | name: 连接名称type: 连接类型(如 "sql", "snowflake")或类**kwargs: 传递给连接类的参数 |
SQLConnection | st.connection(..., type="sql") | 通用 SQL 数据库连接,支持 SQLite、PostgreSQL、MySQL、BigQuery 等。 | url: 数据库连接字符串dialect: SQL 方言 |
SnowflakeConnection | st.connection("sf", type="snowflake", ...) | 专为 Snowflake 数据仓库优化的连接。 | account, user, password, database, schema 等 |
BaseConnection | class MyConnection(BaseConnection[ClientType]): ... | (高级)自定义连接类的基类,用于扩展 st.connection 支持新服务。 | 需实现 ._connect() 方法返回客户端实例 |
SnowparkConnection | st.connection("snowpark", type="snowpark", ...) | 连接到 Snowflake Snowpark(DataFrame API),用于大规模数据处理。 | 参数同 SnowflakeConnection |
连接类型对比:
| 连接类型 | 适用场景 | 返回对象 | 查询方法 |
|---|---|---|---|
"sql" | 通用 SQL DB(SQLite, PG, MySQL) | SQLConnection | .query() |
"snowflake" | Snowflake 查询 | SnowflakeConnection | .query() |
"snowpark" | Snowflake Snowpark(大数据) | SnowparkConnection | .session(Snowpark Session) |
| 自定义类 | REST API、NoSQL、特殊服务 | 自定义客户端 | 自定义方法 |
配置
| 功能 | 函数签名 / 语法 | 函数用途 | 主要参数 |
|---|---|---|---|
config.toml | 文件路径:~/.streamlit/config.toml(全局)或 .streamlit/config.toml(项目级) | 定义 Streamlit 全局或项目级默认配置,影响运行行为、主题、服务器设置等。 | 支持 [server], [client], [theme], [logger] 等 section |
st.get_option() | st.get_option(name) | 获取当前 Streamlit 运行时配置项的值。 | name (str): 配置项的路径,如 "server.port", "theme.base" |
st.set_option() | st.set_option(name, value) | 在运行时动态设置某些可变的配置项(仅限允许运行时修改的选项)。 | name (str): 配置项名称value: 要设置的值 |
st.set_page_config() | st.set_page_config(page_title="My App", page_icon="🦈", layout="wide", initial_sidebar_state="expanded", menu_items={...}) | 配置单个页面的元信息和布局,必须在脚本最开始调用(在任何其他 st. 命令之前)。 | page_title: 浏览器标签页标题page_icon: 标题栏图标layout: "centered" 或 "wide"initial_sidebar_state: 侧边栏初始状态menu_items: 自定义帮助菜单 |
常用配置项:
| 配置 Section | 常见配置项 | 说明 |
|---|---|---|
server | port, address, enableCORS, maxUploadSize | 服务器行为 |
client | caching, spinner, debug | 客户端行为 |
theme | base, primaryColor, backgroundColor, textColor, font | 主题颜色与字体 |
runner | magicEnabled, installTracer | 运行时行为 |
logger | level, file_format, stream_format | 日志配置 |
browser | serverAddress, gatherUsageStats | 浏览器相关设置 |
命令行
| 命令 | 命令签名 / 语法 | 命令用途 | 主要参数 |
|---|---|---|---|
streamlit run | streamlit run [OPTIONS] filename.py [ARGS]... | 运行一个 Streamlit 脚本,启动本地服务器并打开浏览器。 | --server.port: 指定端口(默认 8501)--server.address: 绑定地址--browser.gatherUsageStats=false: 禁用使用统计[ARGS]...: 传递给脚本的自定义参数 |
streamlit config show | streamlit config show | 显示当前所有配置项的值(包括默认值、配置文件值、环境变量覆盖等)。 | 无参数 |
streamlit cache clear | streamlit cache clear | 清除所有缓存数据(@st.cache_data 和 @st.cache_resource)。 | 无参数 |
streamlit docs | streamlit docs | 在浏览器中打开 Streamlit 官方文档。 | 无参数 |
streamlit version | streamlit version | 显示当前安装的 Streamlit 版本。 | 无参数 |
streamlit list-commands | streamlit list-commands | 列出所有可用的 streamlit 命令。 | 无参数 |
streamlit help | streamlit help 或 streamlit help <command> | 显示帮助信息,可查看所有命令或特定命令的用法。 | <command>: 可选,指定子命令 |
命令分类与使用场景:
| 类别 | 命令 | 典型用途 |
|---|---|---|
| 应用运行 | streamlit run | 启动应用,开发调试 |
| 配置管理 | streamlit config show | 调试配置问题,确认设置生效 |
| 缓存管理 | streamlit cache clear | 清除缓存,强制重新加载数据或模型 |
| 文档与帮助 | streamlit docs, streamlit help | 学习 API、查看命令用法 |
| 版本信息 | streamlit version | 检查版本,确保兼容性 |
高级技巧:
使用环境变量设置配置:
# 通过环境变量指定端口
STREAMLIT_SERVER_PORT=9000 streamlit run app.py
# 禁用自动打开浏览器
STREAMLIT_BROWSER_SERVER_ADDRESS=localhost streamlit run app.py
在 Docker 中运行:
CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
调试模式运行:
streamlit run app.py \
--global.developmentMode=true \
--logger.level=debug \
--browser.gatherUsageStats=false
传递自定义参数给脚本:
streamlit run app.py --user=admin --mode=preview