news 2026/9/20 8:55:36

Streamlit实战指南:从PyCharm配置到WebView部署的完整教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Streamlit实战指南:从PyCharm配置到WebView部署的完整教程

Streamlit 这几年在数据圈子里火得不行,几乎成了 Python 数据分析师和算法工程师做 Demo 的标配工具。它最吸引人的地方在于:你只要写纯 Python 脚本,不用碰任何前端代码,就能把数据应用、模型演示、报表看板直接跑成网页。很多朋友第一次在 PyCharm 里跑通streamlit run app.py看到浏览器弹出界面的时候,都会有一种"原来做 Web 应用可以这么简单"的感叹。这篇教程我打算从零开始,把 Streamlit 的核心概念、常用组件、状态管理、性能优化,以及最近群里问得特别多的两个问题——WebView 加载 Streamlit 地址白屏、PyCharm 里怎么配置项目——一次性讲透。内容偏实战,每一步我都会说清楚为什么这么写,适合刚入门的新手,也适合想系统梳理一遍的进阶用户。

1. 整体设计与思路拆解:Streamlit 到底解决了什么问题

1.1 为什么选 Streamlit 而不是 Flask 或 Django

聊 Streamlit 之前,先说说它和传统 Web 框架的区别。用 Flask 写一个数据展示页面,你得懂 HTML 模板、路由、请求处理,还得把 DataFrame 序列化成 JSON 传到前端,再用 JavaScript 渲染。这一套流程对纯做数据分析的人来说,学习成本实在太高了。Streamlit 的核心理念是"脚本即应用":你从上到下写 Python 代码,Streamlit 自动帮你把代码执行结果渲染到网页上,每次交互触发重跑,整个页面自动更新。这背后其实是一个"每次交互全量重跑脚本"的执行模型。

这个设计思路和 Flask 完全不同。Flask 是传统的请求-响应模型,每个 URL 对应一个视图函数,页面之间靠路由跳转;Streamlit 则像一个"带状态的脚本执行器",用户在页面上点击按钮、滑动滑块、输入文本,这些操作会作为新的输入参数重新从上到下执行一遍你的脚本,然后生成新的 UI。这种模型牺牲了一部分性能,但换来了极低的开发门槛——你不需要理解前后端分离,不需要写一行 JavaScript。

从我的实际使用体验来看,Streamlit 最适合这几类场景:数据分析报告的交互化展示、机器学习模型的快速 Demo、内部工具和数据看板、给非技术同事用的数据查询界面。如果你的目标是给客户交付一个生产级、需要复杂权限控制的商用系统,那 Streamlit 可能不是最优解,它更偏向于快速验证和内部效率工具。

1.2 核心执行模型:自上而下、遇交互则重跑

理解 Streamlit 的第一步,是接受它"脚本重跑"的执行机制。你每次和页面交互,Streamlit 就把整个脚本从第一行到最后一行重新执行一遍,然后基于新的状态渲染出最新界面。这个机制导致了一个经典坑:如果脚本里有耗时操作(比如加载大文件、训练模型),每次点按钮都会重复执行一次,页面会卡住。

解决办法就是把耗时操作尽量放到缓存里。Streamlit 提供了@st.cache_data@st.cache_resource两个装饰器,前者缓存数据加载和计算密集型函数的结果,后者缓存全局资源(比如数据库连接、模型实例)。加了这两个装饰器之后,同样的参数只会真正执行一次函数,后续直接命中缓存,速度提升非常明显。这个设计我后文会专门展开讲,因为它是 Streamlit 应用中"快和慢"的分水岭。

还有一个初学者容易困惑的点:页面上多个组件之间是怎么通信的?答案是 session_state。Streamlit 每次重跑脚本时,本地变量都会重新赋值,如果想让某个值跨重跑保留,就必须放进st.session_state里。这个字典对象是跨脚本重跑持久化的,相当于前端浏览器的 localStorage,用起来非常顺手。

1.3 开发体验的取舍:适合谁、不适合谁

我不建议无脑吹 Streamlit。它确实把 Web 开发的门槛拉低了,但代价是自定义能力受限。如果你需要高度定制化的页面样式、复杂的交互动效,Streamlit 的组件层会比较难扩展。好在社区生态已经比较成熟,有大量的st.*组件和第三方插件(比如streamlit-aggrid做表格筛选、streamlit-echarts做图表)可以弥补不少缺口。

说到底,选不选 Streamlit 取决于项目诉求。我的经验是:开发周期在两三天内、核心价值在数据和逻辑本身、用户量在百人级别以内的工具类应用,用 Streamlit 最合适。超过这个规模,再考虑 React + FastAPI 这种前后端分离方案。

2. 环境准备与 PyCharm 配置实战

2.1 安装 Streamlit 与环境隔离

安装很简单,但我强烈建议先把 Python 虚拟环境建好。很多同学在 PyCharm 里装了一堆包之后,某个依赖版本冲突导致 Streamlit 启动报错,排查半天最后发现是全局环境被搞乱了。这一步我个人的习惯是先用python -m venv或者 conda 创建独立环境,再装依赖。

# 创建虚拟环境(Windows 和 macOS/Linux 命令略有差异) python -m venv streamlit_env # 激活环境 # Windows: streamlit_env\Scripts\activate # macOS/Linux: source streamlit_env/bin/activate # 安装 Streamlit pip install streamlit # 验证版本 streamlit version

装完之后,跑一下自带的 Hello 示例验证环境是否正常:

streamlit hello

如果浏览器弹出官方示例界面,说明环境没问题。这一步要是界面上有报错,多半是端口被占用或者依赖包版本冲突,后面我会给出排查思路。

2.2 PyCharm 中配置 Streamlit 运行方式

在 PyCharm 里运行 Streamlit,很多新手会直接点右上角 Run 按钮,然后发现终端里报错 "No module named streamlit" 或者直接没反应。这是因为 Streamlit 应用不是常规的 Python 文件执行方式,它需要通过streamlit run命令启动,而不是python app.py

配置方法其实很简单,我推荐两种方式。

第一种是配置 Run Configuration:

  1. 打开 PyCharm 菜单栏 Run -> Edit Configurations。
  2. 点击左上角加号,选择 Python。
  3. Name 随意填,比如Streamlit App
  4. Script path 选择你虚拟环境里的 streamlit 命令行入口,通常在streamlit_env/Scripts/streamlit.exe(Windows)或者streamlit_env/bin/streamlit(macOS/Linux)。如果你不确定入口路径,可以在终端执行which streamlit查看。
  5. Parameters 填run app.py(假设你的主文件叫 app.py)。
  6. Working directory 设置为项目根目录。

第二种方式更省事,直接在 PyCharm 的 Terminal 里手动激活环境再启动:

streamlit_env\Scripts\activate streamlit run app.py

我个人比较喜欢第二种,因为配置一次之后,后续只需要重复两条命令,而且能看到完整的日志输出。再搭配 PyCharm 的 "Auto Import" 和代码补全,开发体验其实蛮舒服的。

这里有一个很多人踩过的坑:如果你在 PyCharm 的项目解释器里已经选好了虚拟环境,但点击运行按钮还是报找不到模块,大概率是 Run Configuration 用的 Python 解释器和实际环境的解释器不一致。检查一下 Settings -> Project -> Python Interpreter 是否指向streamlit_env,再把 Run Configuration 的 Python Interpreter 也改对,问题就解决了。

2.3 端口与启动参数说明

Streamlit 启动时默认监听 8501 端口。如果端口被占用,页面会一直打不开,终端里也会提示。可以通过参数指定端口:

streamlit run app.py --server.port 8502

另外几个常用参数也顺便提一下:

  • --server.address 0.0.0.0:允许局域网访问,同一 Wi-Fi 下的手机或同事电脑可以直接通过你的 IP 访问应用。
  • --server.headless true:禁止自动打开浏览器,适合服务器环境部署时使用。
  • --server.fileWatcherType auto:文件变更自动重载脚本,开发时非常方便。

我在开发的时候习惯把文件监视器开着,这样改完代码保存,浏览器页面会自动刷新,不用手动重启服务,效率提升很明显。

3. 核心 API 详解与第一个完整应用

3.1 文本、数据、图表三件套

Streamlit 最常用的就三个系列:文本展示、数据展示、图表展示。文本方面有st.titlest.headerst.subheaderst.write,其中st.write是万金油,能自动识别传入对象类型并选择合适的渲染方式。数据方面是st.dataframest.table,前者支持排序、滚动、列宽自适应,交互更丰富,后者就是静态表格。

图表方面和 Pandas 配合最丝滑。直接用st.line_chart(df)st.bar_chart(df)st.area_chart(df)就能出图,本质上底层用的是 Altair。如果要做更复杂的可视化,可以用 Plotly:

import streamlit as st import pandas as pd import plotly.express as px # 模拟一份销售数据 df = pd.DataFrame({ "月份": ["1月", "2月", "3月", "4月", "5月"], "销售额": [120, 190, 170, 240, 310], "成本": [80, 120, 110, 150, 180], }) st.title("销售数据看板") st.write("这是月度销售情况概览,数据为示例数据。") col1, col2, col3 = st.columns(3) col1.metric("总销售额", f"{df['销售额'].sum()} 万") col2.metric("平均销售额", f"{df['销售额'].mean():.1f} 万") col3.metric("最高月销售额", f"{df['销售额'].max()} 万") st.dataframe(df) fig = px.bar(df, x="月份", y=["销售额", "成本"], barmode="group") st.plotly_chart(fig)

把这段代码保存为app.py,然后运行streamlit run app.py,几秒钟就能看到一个带指标卡、表格和交互式图表的页面。这套组合几乎覆盖了 80% 的数据展示需求。

3.2 常用交互组件的正确打开方式

交互组件是 Streamlit 的灵魂。你只需要关心"用户输入了什么",不用管"怎么传递和响应",因为脚本重跑机制已经替你解决了。常用的组件包括:

  • st.button:按钮,返回 True/False,每次点击触发一次重跑。
  • st.text_input:单行文本输入框。
  • st.text_area:多行文本输入框。
  • st.selectbox:下拉选择框。
  • st.multiselect:多选下拉框。
  • st.slider:滑动条。
  • st.radio:单选按钮。
  • st.checkbox:复选框。
  • st.file_uploader:文件上传。
  • st.date_inputst.time_input:日期和时间选择。

组件的返回值基本都是用户在界面上的当前值,直接赋值给变量使用即可。举一个带筛选功能的例子:

import streamlit as st import pandas as pd df = pd.read_csv("sales_data.csv") st.title("订单筛选器") # 侧边栏放筛选控件 with st.sidebar: category = st.selectbox("选择品类", df["品类"].unique()) min_amount = st.slider("最低金额", 0, 1000, 100) filtered = df[(df["品类"] == category) & (df["金额"] >= min_amount)] st.write(f"共 {len(filtered)} 条订单符合条件") st.dataframe(filtered)

筛选逻辑写在组件之后,每次用户调整控件,脚本重跑,筛选结果自动更新。这种"声明式"的交互方式,比传统事件驱动的写法要直观得多。

3.3 st.write 与魔法命令

Streamlit 的st.write可以接收几乎任何对象:字符串、DataFrame、matplotlib 图表、甚至自定义组件。在脚本顶层直接写变量名或表达式,也会被自动渲染到页面上,这个叫魔法命令。比如:

import pandas as pd df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}) # 魔法命令直接输出 df

页面会直接渲染出一个表格。这种写法特别适合在交互式开发阶段快速查看数据,比我一开始用st.write(df)还省事。当然,正式代码里还是建议显式调用st.write,避免可读性下降。

4. 页面布局、状态管理与缓存进阶

4.1 侧边栏、多列、标签页布局方案

真实的工具类应用不可能只是一块竖着的长条内容,Streamlit 也提供了一套布局组件。最常用的是st.sidebar,把筛选条件放左边,主区域放内容,这是数据看板最常见的布局形态。

import streamlit as st st.sidebar.title("控制面板") option = st.sidebar.selectbox("选择视图", ["概览", "明细", "图表"]) threshold = st.sidebar.slider("阈值", 0, 100, 50) st.title(f"当前视图:{option}") st.write(f"当前阈值:{threshold}")

除了侧边栏,st.columns可以把内容排成多列,st.tabs做标签页切换,st.expander做折叠面板,st.container做内容容器。多级页面则用st.navigationst.Page(新版 API)来管理。

对于复杂布局,我建议多用st.container分区,它保证同一容器内的元素在逻辑上是一个整体,配合st.columns可以让不同区块之间互不干扰,这在动态渲染内容时特别重要。

4.2 session_state:跨重跑保留数据的核心机制

前面说过,Streamlit 每次交互都会重跑脚本,普通变量会被重置。如果想让计数器累加、保存用户登录状态、缓存表单输入,就必须借助st.session_state

import streamlit as st # 初始化计数 if "count" not in st.session_state: st.session_state.count = 0 def increment(): st.session_state.count += 1 st.button("加一", on_click=increment) st.write(f"当前计数:{st.session_state.count}")

这里有一个细节值得注意:on_click回调里的代码是在按钮点击时执行的,而不是在脚本重跑时执行的。如果直接在脚本顶层写st.session_state.count += 1,会因为重跑逻辑导致计数被重复增加。所以需要修改状态时,要么写成回调函数,要么先执行修改再更新 UI,思路要转过来。

st.session_state还有一个常见用途是保持输入框的历史值,或者实现"上一步/下一步"的分步表单功能。前者只要给组件加一个key参数,Streamlit 会自动把当前值存到st.session_state[key]里面,读取和修改都很方便。

4.3 缓存机制:从慢到快的分水岭

之前提到的@st.cache_data@st.cache_resource,这里展开说说。@st.cache_data会基于函数参数做哈希,参数相同就返回缓存结果。对于耗时的数据加载、ETL、爬虫抓取,缓存是立竿见影的优化手段。

import streamlit as st import pandas as pd @st.cache_data def load_data(file_path): # 模拟耗时读取 df = pd.read_csv(file_path) return df df = load_data("data.csv")

第一遍执行时函数真的跑一次,之后无论页面怎么重跑、用户怎么交互,只要文件路径没变,都会直接命中缓存,页面响应速度会快好几个数量级。

@st.cache_resource则适合缓存那些不宜被序列化、需要保持全局唯一状态的资源,比如sqlalchemy的数据库连接引擎、已训练好的机器学习模型对象。它的生命周期和缓存对象绑定,直到脚本重启或缓存被主动清理。

注意两个容易踩的坑:一是缓存函数要保证"同样的输入永远得到同样的输出",如果你在函数内部用了随机数或时间函数,缓存会导致结果不再更新;二是如果数据源文件更新了,缓存不会自动失效,你可以调用load_data.clear()手动清理,或者给函数加一个version参数变化时自然刷新。

5. 数据处理、文件上传与实战案例整合

5.1 文件上传与实时解析

企业内部工具里,最常出现的需求就是"上传 Excel,让我筛一筛、看一看"。Streamlit 的st.file_uploader可以直接接收文件对象,配合 Pandas 解析非常顺手。

import streamlit as st import pandas as pd uploaded = st.file_uploader("上传 Excel 或 CSV 文件", type=["csv", "xlsx"]) if uploaded is not None: # 根据后缀选择解析方式 if uploaded.name.endswith(".csv"): df = pd.read_csv(uploaded) else: df = pd.read_excel(uploaded) st.write(f"文件共 {df.shape[0]} 行,{df.shape[1]} 列") st.dataframe(df.head(100))

需要注意的是,st.file_uploader返回的是一个BytesIO对象,不是文件路径。直接用 Pandas 读取没问题,但如果你想用pd.read_excel读取.xlsx,需要先安装openpyxl库,否则会报错。

5.2 实战:一个订单数据快速查询工具

把前面的知识点整合起来,我做一个完整的工具:上传订单文件,侧边栏选择品类、金额区间和日期范围,主区域展示筛选结果和汇总图表。

import streamlit as st import pandas as pd import plotly.express as px st.set_page_config(page_title="订单查询工具", layout="wide") @st.cache_data def load_data(uploaded_file): if uploaded_file.name.endswith(".csv"): return pd.read_csv(uploaded_file) else: return pd.read_excel(uploaded_file) st.title("订单数据快速查询工具") uploaded = st.file_uploader("上传订单文件", type=["csv", "xlsx"]) if uploaded is None: st.info("请先上传文件") st.stop() df = load_data(uploaded) # 将日期列转为 datetime if "日期" in df.columns: df["日期"] = pd.to_datetime(df["日期"]) with st.sidebar: st.header("筛选条件") categories = st.multiselect("品类", df["品类"].unique(), default=df["品类"].unique()) amount_col = st.selectbox("金额列", df.columns) min_val = float(df[amount_col].min()) max_val = float(df[amount_col].max()) amount_range = st.slider("金额范围", min_val, max_val, (min_val, max_val)) mask = df["品类"].isin(categories) mask &= df[amount_col].between(*amount_range) if "日期" in df.columns: date_min = df["日期"].min().date() date_max = df["日期"].max().date() date_range = st.sidebar.date_input("日期范围", [date_min, date_max]) mask &= (df["日期"].dt.date >= date_range[0]) & (df["日期"].dt.date <= date_range[1]) filtered = df[mask] c1, c2, c3 = st.columns(3) c1.metric("订单数", len(filtered)) if len(filtered) > 0: c2.metric("总金额", f"{filtered[amount_col].sum():,.2f}") c3.metric("平均金额", f"{filtered[amount_col].mean():,.2f}") st.dataframe(filtered, use_container_width=True) if len(filtered) > 0 and "品类" in filtered.columns: fig = px.bar(filtered.groupby("品类")[amount_col].sum().reset_index(), x="品类", y=amount_col, title="各品类金额汇总") st.plotly_chart(fig, use_container_width=True)

这个例子涉及文件上传、缓存、侧边栏联动、数据筛选、指标卡和图表的完整链路,基本能代表 Streamlit 开发的一个标准节奏。

5.3 下载结果与导出

做工具的时候,用户筛完数据往往要导出。Streamlit 提供了st.download_button,可以把 DataFrame 转成 CSV 字符串或者 Excel bytes 供用户下载。

import pandas as pd import streamlit as st csv_data = filtered.to_csv(index=False).encode("utf-8-sig") st.download_button( label="下载筛选结果 CSV", data=csv_data, file_name="filtered_result.csv", mime="text/csv", )

加上utf-8-sig编码可以防止 Excel 打开 CSV 时中文乱码,这是我在给同事交付工具时踩过的一个小坑。

6. 常见问题与排查技巧实录

6.1 WebView 加载 Streamlit 地址白屏问题

最近群里问得最多的问题,就是"把 Streamlit 的 URL 放到 App 的 WebView 里,打开一片白"。

这个问题我折腾过不少时间,先说结论:WebView 白屏的原因通常不是 Streamlit 本身坏了,而是 WebView 默认没有开启 JavaScript,或者 WebView 无法访问 Streamlit 的长轮询连接。

Streamlit 的页面渲染依赖 WebSocket 和服务端通信。在浏览器里,页面先加载 HTML,然后通过 WebSocket 建立连接,服务端推送脚本执行结果,再由前端 JavaScript 渲染。WebView 加载 Streamlit 地址时,如果JavaScriptEnabled是关闭的,页面完全无法执行任何脚本,自然就是白屏。

解决办法因平台而异。在 Android 原生 WebView 里,要这样设置:

WebView webView = findViewById(R.id.webview); webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setDomStorageEnabled(true); webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); webView.loadUrl("http://你的服务器IP:8501");

这里有几个关键设置:

  • setJavaScriptEnabled(true):必须开启,否则 Streamlit 的前端脚本跑不起来。
  • setDomStorageEnabled(true):Streamlit 会用到 localStorage 和 sessionStorage 管理状态,关了也会出问题。
  • MixedContentMode:如果你的 Streamlit 服务是 HTTP 而 WebView 外层页面是 HTTPS,不设置这个会拦截混合内容,同样白屏。

如果是 iOS 的 WKWebView,对应的配置是要允许任意加载:

let webView = WKWebView() webView.configuration.preferences.javaScriptEnabled = true webView.load(URLRequest(url: URL(string: "http://服务器IP:8501")!))

还需要在 Info.plist 里配置NSAppTransportSecurity允许 HTTP 加载,否则 iOS 默认会拦截所有非 HTTPS 请求。

另外还有一个细节:如果 WebView 的 UA 被设置成了移动端浏览器,Streamlit 部分老版本对移动端布局支持不好,也可能导致内容不显示。可以考虑给 WebView 设置一个桌面端 UA。

6.2 PyCharm 中运行 Streamlit 的典型报错

PyCharm 相关最常见的问题有三个:

第一个是运行后提示streamlit: command not found。这说明当前终端环境里没有 streamlit 命令,通常是 PyCharm 默认的终端没有激活虚拟环境。解决方法是检查 PyCharm 的 Terminal 设置里的 Shell path,或者手动在终端里先激活环境再运行。

第二个是ModuleNotFoundError: No module named 'streamlit'。这个基本确定是解释器选错了。在 Settings -> Project -> Python Interpreter 里确认当前项目用的是哪个环境,把解释器切换到安装了 streamlit 的虚拟环境,再重新运行。

第三个是运行后浏览器打开 显示 connection refused。这种情况要么是服务没起来,要么是端口被防火墙拦了。先在终端里看有没有 Streamlit 的启动日志,如果日志正常,就检查防火墙是否允许 8501 端口,或者换一个端口试试。

6.3 其他高频问题速查

我把日常开发遇到的高频问题整理成一个速查表,方便大家对照处理。

问题现象可能原因解决办法
页面一直转圈不显示WebSocket 被防火墙或代理拦截检查网络环境,确认 8501 端口可达
修改代码后页面不刷新文件监视器未生效确认--server.fileWatcherType配置,或手动刷新浏览器
多个用户同时使用数据错乱全局变量在重跑中互相干扰使用st.session_state而非模块级全局变量
上传文件后每次交互卡顿没有使用缓存给文件读取函数加@st.cache_data
侧边栏控件状态总是重置组件未设置key导致无法定位状态为每个组件添加唯一的key参数
部署到公网后样式丢失静态资源路径问题确认使用streamlit run而非直接托管静态文件

这里想特别强调key参数。很多人在页面里写了两个st.selectbox,偶尔发现切换其中一个时另一个也变了,就是因为没指定key,Streamlit 内部按组件类型和顺序识别状态,结构一变就容易串。给每个交互组件一个明确唯一的key,是最省心的习惯。

6.4 部署时容易忽视的细节

本地跑通之后,大家通常会想把应用分享出去。Streamlit 官方有 Community Cloud 可以直接部署,绑定 GitHub 仓库就行。但国内访问速度不稳定,我通常建议部署到自己的云服务器上。

部署时注意几点:先用pip freeze > requirements.txt导出依赖;服务器上建议也用虚拟环境;然后用nohup streamlit run app.py --server.port 8501 --server.address 0.0.0.0 > app.log 2>&1 &后台启动。如果想做更正规的进程管理,可以用 systemd 或者 supervisor,把 Streamlit 注册成系统服务,崩溃后自动重启。

公网部署还要考虑 HTTPS。如果通过 Nginx 反向代理,需要配置 WebSocket 升级头,否则页面能打开但交互无响应。在 Nginx 配置里要加上:

location / { proxy_pass http://127.0.0.1:8501; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; }

这里UpgradeConnection是关键,WebSocket 长连接依赖这两个头才能正常建立。

6.5 调试技巧:st.write 是一个万能调试器

最后分享一个我在开发中天天用的调试技巧:遇到不知道组件返回了什么值、不确定 DataFrame 长什么样,直接在代码里用st.write打印出来。因为它能自动渲染各种类型,比print更适合 Streamlit 的交互式开发节奏。

st.write("当前筛选结果前5行:") st.write(filtered.head())

配合页面上实时展示的输出,你能立刻看到每组输入对应的中间结果,定位问题比看日志快得多。等调试完了,再把这些调试输出删掉或者放到st.expander折叠起来,避免污染正式界面。

我个人在实际操作中的体会是,Streamlit 的上手曲线其实很短,花一个下午看完常用 API,再独立做一个小工具,基本就能掌握大部分用法。真正拉开差距的是对执行模型的理解——什么时候重跑、什么该进缓存、什么状态该放 session_state、什么时候该用回调函数。把这些想明白了,写出来的应用又快又稳。最后一个建议:从一个小的真实需求开始练手,比如把自己的日报数据做成一个筛选面板,比照着教程抄十遍都管用。动手跑通第一个应用,那种成就感会推着你继续往下深入。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 8:55:07

垃圾分类目标检测系统实战:从数据集处理到YOLOv8部署

简介&#xff1a;一套基于深度学习的垃圾分类目标检测系统源码&#xff0c;面向Python毕业设计、课程实践与深度学习入门人群。项目以目标检测模型为核心&#xff0c;配套后端服务、前端页面与容器化部署配置&#xff0c;帮助学习者快速走通从环境准备到模型推理的完整流程。压…

作者头像 李华
网站建设 2026/9/20 8:51:27

基于Python+MySQL+ECharts的图书馆数据可视化系统开发实践

简介&#xff1a;面向毕业设计场景的 Python 图书馆大数据可视化分析系统完整项目包&#xff0c;整合 Python 后端、MySQL 数据库、前端展示与说明文档&#xff0c;解决图书馆数据分散、查询分析依赖手工统计、结果不够直观等问题。系统基于 Pandas、NumPy 完成数据清洗与计算&…

作者头像 李华
网站建设 2026/9/20 8:51:16

cursor-skills 同步 AGENTS.md 后,read 给 Agent 用:Base URL 走 TaoToken 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 8:50:50

NASA开放数据API实战:Python获取与处理航天数据

1. 项目概述&#xff1a;NASA数据接口的价值与应用场景NASA作为全球顶尖的航天机构&#xff0c;其开放数据门户&#xff08;data.nasa.gov&#xff09;提供了超过32,000个数据集&#xff0c;涵盖地球观测、天体物理、气候研究等多个领域。这些数据通过API接口向公众开放&#x…

作者头像 李华