Streamlit指南:46k星Python数据应用框架,几行代码做出Web界面

项目:streamlit/streamlit | 星数:46173 | 语言:Python | 协议:Apache-2.0 | GitHub仓库

更新日期:2026-10-29 · 作者:CodeArts 编辑部

它省掉的是哪一层

想给一个 Python 脚本配界面,传统做法要拆成前后端:写接口、写页面、处理 CORS、打包部署。Streamlit 把这一整层抹掉了——你写 Python,从上到下按顺序调用组件,页面就按顺序渲染。改一行代码保存,浏览器里立刻刷新。

46173 星、Apache-2.0,它现在最常见的用途是两类:内部数据工具(查询、报表、打标)和 AI 应用的演示界面(聊天、RAG 问答、模型对比)。

安装与第一个应用

pip install streamlit
streamlit run app.py
import streamlit as st

st.title('销售看板')
name = st.text_input('你的名字')
if name:
    st.write(f'你好,{name}')

import pandas as pd
df = pd.DataFrame({'月份': ['1月','2月','3月'], '销售额': [120, 180, 150]})
st.dataframe(df)
st.bar_chart(df.set_index('月份'))

默认起在 8501 端口,保存文件后页面右上角出现"Rerun"提示,选 Always rerun 就是热重载。

执行模型:每次交互整脚本重跑

这是理解 Streamlit 的第一把钥匙。用户点任何控件,整个脚本会从上到下重新执行一遍。所有变量重新计算,所有组件重新渲染。好处是无需管理状态,坏处是耗时操作会被反复触发——于是有了缓存。

缓存:两种,别用混

装饰器缓存对象典型用途
@st.cache_data返回值(会序列化)读 DataFrame、调 API、算统计
@st.cache_resource对象本身(全局共享)数据库连接、模型、tokenizer
@st.cache_data(ttl=600)
def load_orders(date):
    return pd.read_sql(f"select * from orders where d='{date}'", conn)

@st.cache_resource
def get_model():
    from sentence_transformers import SentenceTransformer
    return SentenceTransformer('BAAI/bge-small-zh-v1.5')

最常见的坑是把模型加载放进 cache_data,每次都要序列化反序列化,反而更慢;反过来把数据库连接放进 cache_data,连接对象不可序列化会直接报错。判断标准很简单:会变的数据用 data,重对象用 resource。

会话状态:跨重跑保存变量

聊天记录、多步表单的中间结果,都需要跨脚本重跑保留:

if 'messages' not in st.session_state:
    st.session_state.messages = []

prompt = st.chat_input('说点什么')
if prompt:
    st.session_state.messages.append({'role': 'user', 'content': prompt})
    reply = my_llm(prompt)
    st.session_state.messages.append({'role': 'assistant', 'content': reply})

for m in st.session_state.messages:
    with st.chat_message(m['role']):
        st.markdown(m['content'])

这就是一个流式聊天界面的骨架,十行左右。想加流式输出,把 reply = my_llm(prompt) 换成 st.write_stream(gen) 即可。

控件与布局:够用就好

表单场景用 with st.form('f'): 包起来,用户填完点提交才触发重跑,否则每改一个字段就重算一次,体验很差。

多页面:不要自己造路由

Streamlit 原生支持多页:在入口文件同目录建 pages/ 文件夹,里面的 1_数据概览.py、2_模型评测.py 会自动出现在左侧导航。文件名前缀数字控制顺序。小项目用这个就够,不需要引入额外路由库。

部署与暴露的两种方式

# 内网/自己服务器
streamlit run app.py --server.port 8501 --server.address 0.0.0.0

# 容器化
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8501
CMD ["streamlit", "run", "app.py", "--server.address=0.0.0.0"]

Streamlit 官方社区云可以直连 GitHub 仓库一键部署,免费额度适合演示;但如果应用涉及内部数据或 API Key,务必自托管。放在反向代理后时记得设置 --server.baseUrlPath 和 --server.enableCORS=false,否则会出现 websocket 连不上的白屏。

什么场景不该用它

Streamlit 不是通用 Web 框架。需要精细 UI 设计、复杂前端交互、SEO 友好的对外站点、高并发的公共产品,它都不合适——每次交互都整脚本重跑的执行模型注定了并发能力有限。它最佳的位置是:内部工具、数据探索、模型演示、原型验证。认清这个边界,用起来会很舒服。

常见问题

Streamlit 和 Gradio 该怎么选?

两者定位接近。Streamlit 更偏数据应用和仪表盘,布局能力强、表格与图表生态好;Gradio 更聚焦模型演示界面,几行代码就能暴露一个推理函数,且对 HuggingFace Spaces 集成更顺。做数据看板选 Streamlit,做模型 demo 选 Gradio。

cache_data 和 cache_resource 用错会怎样?

把数据库连接或大模型放进 cache_data,对象需要序列化,会直接报错或性能骤降;把可变的 DataFrame 放进 cache_resource,多个用户会共享同一份数据并可能被互相污染。原则:会变的数据用 cache_data,重且共享的对象用 cache_resource。

Streamlit 能扛住多少并发?

不适合高并发。每个会话的交互都会触发完整脚本重跑,资源消耗与用户数成正比,免费社区云也有资源限制。内部工具几十人同时使用没问题;面向公众的高并发产品应选 FastAPI + 前端框架。