Streamlit 使用记录
基础
安装
# 虚拟环境构建
conda create -n stenv python=3.9
conda activate stenv # source activate stenv
# 安装
pip install streamlit
# 查看是否安装成功
streamlit hello
简单运行
# file 001.py
import streamlit as st
st.write('Hello world!')
Run
streamlit run 001.py
使用
常用导入
import streamlit as st
import pandas as pd
import numpy as np
import altair as alt
大部分的基础操作可在 Cheet Sheet , API Reference , Streamlit Magic Cheat Sheets中找到
显示
用于页面显示的常用组件
文本
st.write('Hello')
st.markdown("# This is a Markdown Title")
# st.tiltle / st.header / st.subheader / st.text / st.caption / st.divider
数字
st.write(1234)
公式
st.latex(r''' e^{i\pi} + 1 = 0 ''')
代码块
st.code("""
for i in range(8):
foo()
""")
dataframe
df = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [10, 20, 30, 40]})
st.dataframe(df)
指标卡
st.metric(label="Temperature", value="70 °F",delta="1.2 °F", delta_color="inverse")
# 一行3列
col1, col2, col3 = st.columns(3)
col1.metric("Temperature", "70 °F", "1.2 °F")
col2.metric("Wind", "9 mph", "-8%")
col3.metric("Humidity", "86%", "4%")
绘图
c = alt.Chart(df).mark_circle().encode(x='a', y='b', tooltip=['a', 'b'])
st.write(c)
多媒体
st.image('./header.png',width=200)
st.audio(data)
st.video(data)
布局
页面初始设置
# Setting page layout
st.set_page_config(
page_title="ZJun",
page_icon="🤖",
layout="wide",
initial_sidebar_state="expanded"
)
侧边栏
with st.sidebar:
st.write("This is a sidebar")
多列
col1, col2, col3 = st.columns(3)
with col1:
st.xxx
with col2:
st.xxx
with col3:
st.xxx
多Tab
tab1, tab2, tab3 = st.tabs(["Cat", "Dog", "Owl"])
with tab1:
st.xxx
with tab2:
st.xxx
with tab3:
st.xxx
展开
with st.expander("See More"):
st.write("test")
容器
with st.container():
st.write("This is inside the container")
st.write("This is outside the container")
多页面
- 001.py
- pages
- 002.py
- 003.py
类似如上目录结构,然后运行最外围的 001.py 即可
操作
用户和页面的交互
按钮
c = st.button("Click me")
跳转
st.link_button("Go to gallery", "https://streamlit.io/gallery")
滑块
age = st.slider('How old are you?', 0, 130, 25)
# 最小值、最大值和默认数值
单选
option = st.selectbox('What is your favorite color?',('Blue', 'Red', 'Green'))
#圈圈
genre = st.radio(
"What is your favorite color?",
['Blue', 'Red', 'Green'],
index=None,
)
多选
options = st.multiselect('Do select',['Green', 'Yellow', 'Red', 'Blue'],['Yellow', 'Red'])
确认框
coffee = st.checkbox('Coffee')
开关
st.toggle("Enable")
编辑dataframe
df = pd.DataFrame({'a': [1, 2, 3, 4], 'b': [10, 20, 30, 40]})
edited_df = st.data_editor(df)
st.markdown(f"[0,1] is **{edited_df.iloc[0,1]}**")
输入
文本
text_input = st.text_input("Enter some text",
label_visibility="visible",
disabled=False,
placeholder='Placeholder text')
st.text_area("Text to translate")
number = st.number_input("Insert a number", value=None, placeholder="Type a number...")
日期
d = st.date_input("When's your birthday", value=None)
st.write('Your birthday is:', d)
颜色
st.color_picker("Pick a color")
# return color like #76b776
填报
import streamlit as st
with st.form("my_form"):
st.write("Inside the form")
slider_val = st.slider("Form slider")
checkbox_val = st.checkbox("Form checkbox")
# Every form must have a submit button.
submitted = st.form_submit_button("Submit")
if submitted:
st.write("slider", slider_val, "checkbox", checkbox_val)
st.write("Outside the form")
文件
uploaded_file = st.file_uploader("Choose a file")
if uploaded_file is not None:
stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
string_data = stringio.read()
st.write(string_data)
uploaded_file_csv = st.file_uploader("Choose a csv file", type=["csv"])
if uploaded_file_csv is not None:
dataframe = pd.read_csv(uploaded_file_csv)
st.write(dataframe)
from PIL import Image
from io import BytesIO
image_file = st.file_uploader("Upload Images", type=["png", "jpg", "jpeg"])
if image_file:
st.image(Image.open(image_file), width=250)
# 使用函数(转化为字节流保存)
def convert_image(img):
buf = BytesIO()
img.save(buf, format="PNG")
byte_im = buf.getvalue()
return byte_im
可点击图片
# pip install st-clickable-images
import streamlit as st
from st_clickable_images import clickable_images
clicked = clickable_images(
[
"https://images.unsplash.com/photo-1565130838609-c3a86655db61?w=700",
"https://images.unsplash.com/photo-1565372195458-9de0b320ef04?w=700",
"https://images.unsplash.com/photo-1582550945154-66ea8fff25e1?w=700",
"https://images.unsplash.com/photo-1591797442444-039f23ddcc14?w=700",
"https://images.unsplash.com/photo-1518727818782-ed5341dbd476?w=700",
],
titles=[f"Image #{str(i)}" for i in range(5)],
div_style={"display": "flex", "justify-content": "center", "flex-wrap": "wrap"},
img_style={"margin": "5px", "height": "200px"},
)
st.markdown(f"Image #{clicked} clicked" if clicked > -1 else "No image clicked")
视频
img_file_buffer = st.camera_input("Take a picture")
if img_file_buffer is not None:
# To read image file buffer as a PIL Image:
st.image(Image.open(img_file_buffer))
音频
import streamlit as st
import numpy as np
### 读取
audio_file = open('myaudio.ogg', 'rb')
audio_bytes = audio_file.read()
st.audio(audio_bytes, format='audio/ogg')
### 处理构建
sample_rate = 44100 # 44100 samples per second
seconds = 2 # Note duration of 2 seconds
frequency_la = 440 # Our played note will be 440 Hz
# Generate array with seconds*sample_rate steps, ranging between 0 and seconds
t = np.linspace(0, seconds, seconds * sample_rate, False)
# Generate a 440 Hz sine wave
note_la = np.sin(frequency_la * t * 2 * np.pi)
st.audio(note_la, sample_rate=sample_rate)
下载
表格
import streamlit as st
@st.cache
def convert_df(df):
# IMPORTANT: Cache the conversion to prevent computation on every rerun
return df.to_csv().encode('utf-8')
csv = convert_df(my_large_df)
st.download_button(
label="Download data as CSV",
data=csv,
file_name='large_df.csv',
mime='text/csv',
)
文本
import streamlit as st
text_contents = '''This is some text'''
st.download_button('Download some text', text_contents)
Copy
图片
import streamlit as st
with open("flower.png", "rb") as file:
btn = st.download_button(
label="Download image",
data=file,
file_name="flower.png",
mime="image/png"
)
# file same as uploaded_file type (字节流)
image_file = st.file_uploader("Upload Images", type=["png", "jpg", "jpeg"])
if image_file:
st.image(Image.open(image_file), width=250)
btn = st.download_button(
label="Download image",
data=image_file,
file_name="flower.png",
mime="image/png"
)
辅助
进度条
import time
progress_text = "Operation in progress. Please wait."
my_bar = st.progress(0, text=progress_text)
for percent_complete in range(100):
time.sleep(0.01)
my_bar.progress(percent_complete + 1, text=progress_text)
time.sleep(1)
my_bar.empty()
st.button("Rerun")
进度加载
import time
with st.spinner('Wait for it...'):
time.sleep(5)
st.success('Done!')
error / info / warning / success
st.error('This is an error', icon="🚨")
st.info('This is a purely informational message', icon="ℹ️")
st.warning('This is a warning', icon="⚠️")
st.success('This is a success message!', icon="✅")
数据缓存 @st.cache_data
import streamlit as st
@st.cache_data
def fetch_and_clean_data(url):
# Fetch data from URL here, and then clean it up.
return data
d1 = fetch_and_clean_data(DATA_URL_1)
# Actually executes the function, since this is the first time it was
# encountered.
d2 = fetch_and_clean_data(DATA_URL_1)
# Does not execute the function. Instead, returns its previously computed
# value. This means that now the data in d1 is the same as in d2.
d3 = fetch_and_clean_data(DATA_URL_2)
# This is a different URL, so the function executes.
Session State
Session State is a way to share variables between reruns, for each user session. In addition to the ability to store and persist state, Streamlit also exposes the ability to manipulate state using Callbacks. Session state also persists across apps inside a multipage app.
st.write(st.session_state)
if 'count' not in st.session_state:
st.session_state.count = 0
st.session_state.count += 1
# Every widget with a key is automatically added to Session State:
st.text_input("Your name", key="name")
# This exists now:
st.session_state.name
简单问答模式 (不含对话历史)
import streamlit as st
from langchain.llms import Ollama
llm = Ollama(model="mistral")
# Initialize chat history
if "messages" not in st.session_state:
st.session_state.messages = []
# Display chat messages from history on app rerun
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
if prompt := st.chat_input():
st.chat_message("user").write(prompt)
st.session_state.messages.append({"role": "user", "content": prompt})
response = llm.stream(prompt)
with st.chat_message("assistant"):
placeholder = st.empty()
full_response = ''
for item in response:
full_response += item
placeholder.markdown(full_response)
placeholder.markdown(full_response)
st.session_state.messages.append({"role": "assistant", "content": full_response})
Components
Components are third-party modules that extend what’s possible with Streamlit. Built by creators, for the community
部署
案例
参考
- Streamlit Documentation
- Streamlit Discuss
- Awesome Streamlit
- Streamlit GitHub
- Streamlit Components
- Multi Page APP
- App Gallery
- [[202312081118 Vega-Altair|Vega Altair]]
- Build Streamlit apps in your browser with GitHub Codespaces
- 第三方组件