编程语言研究书库

第一个应用跑起来 — 环境、工作流,和那个密码检查器

第一个应用跑起来 — 环境、工作流,和那个密码检查器

这一章讲三件事: 把开发环境搭对(Git、编辑器、虚拟环境); Streamlit 特有的「保存 → 浏览器里重跑」开发循环; 以及第一个完整应用——密码检查器——从逻辑流到每一行代码。 读完你能自己把一个 Streamlit 应用从 streamlit run 跑到浏览器里, 并且看懂代码里每个 st. 函数在屏幕上对应什么。

1. 这一章讲什么

第 01 章告诉你 Streamlit 值得学;这一章让你真的跑起来。 顺序是:先装(Python 3.9 以上,pip install streamlit)1, 再谈三个影响你今后每一天效率的环境决定2, 然后看一遍开发工作流的全貌3,最后从零写一个密码检查器应用, 再改它、看它热更新、最后杀掉服务器4。

附录(Installing Python and Streamlit)是安装细节的官方出处: macOS 和 Windows 两条路径、怎么查现有 Python 版本(python --version, 附录特意提醒 -V 是大写)5。安装本身没有概念难度,我们不再单独拆一章, 需要的细节都在这一章的原文地图里。

2. 顶层全景:你按下的每个键去了哪里

先建立整张图,后面每一节都是图上的一个框:

  你的代码编辑器          你的终端                     浏览器
  ┌──────────────┐   streamlit run app.py     ┌──────────────────┐
  │  写 app.py    │ ───────────────────────▶  │  localhost:8501  │
  │  保存(Ctrl-S)│   启动 Streamlit 服务器    │  看到应用,点按钮  │
  └──────────────┘         │                  └────────▲─────────┘
        ▲                  │ 监视文件变化                │ 发请求
        │                  ▼                            │
        │           文件一变,浏览器右上角              │
        └─────────── 出现「Rerun / Always Rerun」───────┘

  图说:编辑器是你的,终端里的服务器是 Streamlit 的,浏览器是你的应用的。
  三个窗口,一条循环。

三个要点:(1) streamlit run 启动的是一台服务器——一个常驻进程, 你的终端窗口就是它的家;关终端 = 杀服务器6。 (2) 服务器会监视你的代码文件,保存后浏览器里出现重跑提示7。 (3) 浏览器和服务器说的地址是 http://localhost:8501—— localhost 意思是「我这台电脑」,8501 是 Streamlit 的默认端口号8。

3. 核心原理(一):环境三件套,各自解决一个什么麻烦

这三个工具都不是 Streamlit 特有的,但这本书把它们放在第一章讲,因为它们决定了你之后的开发体验。

Git:代码的时光机。 版本控制(Git 是今天最流行的实现)做的事用一句话说: 给代码的每次变动留一份可回去的历史9。为什么非要它:你会改主意、会试三种设计再挑一个、 半年后看不懂自己当时为什么这么写——Git 让每个「当时」都能回去、都留有说明10。 书里给的定位很务实:第 5.2 节有「够部署用的最小 Git」,想学深去 Atlassian 的教程11。

编辑器:PyCharm 或 VS Code。 Streamlit 应用本质是文本文件,记事本也能写; 但「代码编辑器」提供语法高亮、错误检查、跳转,效率完全是两个量级12。 书里对 IDE(集成开发环境,装上就全配好的那种)和插件化编辑器的分野说得很清楚: PyCharm 是 JetBrains 做的 Python 专用 IDE,开箱即全,Community 版免费13; VS Code 本体轻巧、靠插件生态变全,配好了能做付费版 PyCharm 的一切,还免费14。

这里有一处值得单独记的作者判断:这一节写成之后,AI 优先的编程工具 (Codex、Claude Code、Cursor)已经流行起来,但作者建议学习阶段仍用普通 IDE—— AI 工具日常很强,学基础时会让你跳过本该亲手做的那部分15。

虚拟环境:每个项目一间独立病房。 问题是这样的:不同项目依赖的库版本常常冲突, 给项目 A 升级一个库,项目 B 莫名其故地坏了16。虚拟环境就是给每个项目配一个隔离的 Python 副本,各自的库互不见面17。你会听到 venv、pipenv、pyenv、poetry 这些名字—— 它们是同一类工具的不同实现,选一个用即可18。

为什么这三件排在写代码之前

书里有一句很容易被滑过去的话:环境选择「很大程度上是个人偏好」, 但长期会显著影响你的效率19。翻译一下:工具本身没有对错,但「从没配好过环境的人」 和「环境顺手的人」之间的差距,半年后会大到不成比例。这一章花篇幅讲三件非 Streamlit 的事, 是刻意安排——它不想你卡在「我的库装哪去了」上。

4. 核心原理(二):Streamlit 的开发循环——和其他编程不一样的一步

普通 Python 脚本的循环是:写 → 跑(python app.py)→ 看结果 → 改。 Streamlit 的循环多了一跳,因为应用是「活」在浏览器里的:

  ① 写代码        ② 保存        ③ streamlit run app.py(只跑一次!)
  ④ 在浏览器里试   ⑤ 回编辑器改   ⑥ 保存
  ⑦ 回浏览器,右上角点 Rerun(或 Always Rerun)   ⑧ 回到 ④

  图说:关键在 ⑦——不用重跑 streamlit run,服务器一直在,你要的只是「让脚本再跑一遍」。

「Always Rerun」(旧版本界面叫 Run on Save)打开后,保存即自动重跑,改代码到看效果的 延迟缩到一秒级20;代价是页面整个刷新,改动小的时候不容易看出哪里变了, 所以也可以在设置里关掉、手动点21。还有一条边界情况:改的不是 .py 文件 (应用依赖的文本文件、数据库),偶尔需要杀掉服务器重来——见第 7 节22。

5. 核心原理(三):密码检查器——第一个应用,逐行走一遍

这是本章主线例子。应用的逻辑流(书里 figure 2.5 那张图,我们复述成文字):

  用户在一行输入框里输入密码,点「Check password」
      │
      ▼
  程序手里有一张「规则表」(4 条规则),逐条拿密码去检查
      │
      ▼
  每条规则得到一个结果:PASS 或 FAIL
      │
      ▼
  屏幕上逐条显示:过的打绿框,不过的打红框

  图说:输入 → 检查 → 上色,一条直线,没有回头路。

完整代码(照原书 listing 2.1,注释从简):

import streamlit as st

conditions = {
    'More than 8 characters': lambda pw: len(pw) > 8,
    'At least one uppercase letter':
        lambda pw: any(char.isupper() for char in pw),
    'At least one lowercase letter':
        lambda pw: any(char.islower() for char in pw),
    'At least one special character':
        lambda pw: any(char in ",.!?@#$%^&*()-_+=|\\/:;<>~" for char in pw),
}

def get_password_properties(password):
    return {cond: check(password) for cond, check in conditions.items()}

st.title("Password Checker")
password_input = st.text_input("Enter your password", type="password")

if st.button("Check password"):
    if password_input:
        properties = get_password_properties(password_input)
        for condition, passes in properties.items():
            if passes:
                st.success(f'  ✔  Pass: {condition}')
            else:
                st.error(f'  ✖  Fail: {condition}')
    else:
        st.write("Please enter a password.")

逐行走一遍,拿一个具体输入当标本。 设用户输入 Streamlit1!:

  1. import streamlit as st——引入库,st 是全行业通用的别名,你听到的「st 点什么东西」 说的就是 Streamlit 元素23。
  2. conditions = {...}——一个字典:键是规则的名字(人读的句子), 值是一个 lambda(匿名的单行函数):给它密码,它返回这条规则过没过24。 四条规则分别是:长度 > 8、有大写、有小写、含特殊字符。
  3. get_password_properties(password)——把密码逐条送进四个 lambda, 返回一个新字典 {规则名: True/False};这个写法叫字典推导式25。
  4. st.title("Password Checker")——屏幕上出现大标题。注意:它是无条件执行的, 每次运行都画一次。
  5. password_input = st.text_input("Enter your password", type="password")—— 屏幕上出现一个输入框,type="password" 让输入以圆点遮蔽显示26。 关键:用户输入的文本这一刻就存在 password_input 里了;这一轮脚本往下走时, 用的就是这个值。
  6. if st.button("Check password"):——屏幕上出现按钮。这是全书第一个会咬人的句子: 没点按钮时,这个条件为假,if 里的代码根本不执行;点了按钮、脚本重跑的这一轮, 它才为真27。按钮的「状态」不是存在某个事件回调里,而是就是这一次运行里的一个布尔值。
  7. 假设这一轮按钮是被点的:if 里先确认密码非空,再调 get_password_properties, 然后对四个结果逐条 st.success(绿框)/st.error(红框)28。 对我们的输入 Streamlit1!:长度 11 > 8 ✔、有 S ✔、有小写 ✔、有 ! ✔——四条全绿。 换成 abc:长度 ✖、无大写 ✖、有小写 ✔、无特殊字符 ✖——两绿两红。
  8. 若输入框是空的,st.write("Please enter a password.") 提示先输入29。

这段代码里藏着的三个「第一次」

  • 第一次看见「脚本即界面」:界面上有什么,完全由这一次脚本执行经过哪些 st. 调用决定; 顺序、有无,全是代码的顺序和条件。
  • 第一次看见「按钮 = 一次重跑里的条件」:它没有事件监听,而是「这次运行按钮恰好被按下了」。 第 04 章会告诉你这个设计为什么有力、什么时候反噬。
  • 第一次看见 Streamlit 的调试入口:应用不对,先看「这一轮脚本走到哪了」—— 因为界面就是执行轨迹本身。

6. 跑起来、改它、杀掉它——一条完整的生命周期

跑。 在文件所在目录执行 streamlit run password_checker.py; 终端出现 Local URL: http://localhost:8501(端口号也可能是 8502,占用时会自动换)30。 浏览器没自动打开的话,手动敲那个地址;换个浏览器(Chrome 最稳)也常是解药31。

改。 书里示范的修改:给 conditions 加第五条规则(至少一位数字), 再给按钮文案加个感叹号32。保存后,浏览器右上角立刻出现「source file has changed」 的提示,附 Rerun / Always Rerun 两个选项33。点 Rerun,按钮变成「Check password!」, 数字检查生效。any(char.isdigit() for char in pw) 就是新规则的全部代码34。

杀。 服务器活着,靠的是你那个终端窗口。Ctrl-C(或关窗口)之后, 浏览器里的应用立刻「死」给你看:按钮变灰、右上角转「CONNECTING」35。 再 streamlit run 一次就复活——而且旧的浏览器标签也会跟着活过来, 因为它重新连上了新服务器36。记住这个体感:界面不能脱离服务器存在, 服务器才是应用的本体,浏览器只是它的投影。

7. 作者的判断与证据

判断:学习阶段别用 AI 编程工具。 依据是作者观察到的行业变化 (Codex、Claude Code、Cursor 兴起),论断形式是建议而非论证37。 我们认可方向,但补一句书里没说的:这条建议对「学 Streamlit」适用, 对「用 Streamlit 干活」未必——两者目标不同。

判断:先写个差不多完整的版本再第一次运行,而不是边写边看。 作者明说这是个人偏好:早早看到界面会让人忍不住抠外观,忘了先把逻辑写完38。 这类「工匠偏好」在全书反复出现,读的时候当成「一种被验证过的口味」而非定律。

证据强度备注: 环境三件套(Git/编辑器/虚拟环境)是行业标准实践,证据充分; 「Always Rerun 更顺滑」「Chrome 问题最少」是经验之谈,无对照实验; 密码检查器的逐行走读是可直接复现的操作,你自己跑一遍即可验证。

8. 边界与局限

  • 版本门槛会过期。 书里说 Python 3.9+、推荐 3.11+39;附录写 Streamlit 要 3.10+40。 这两处本身就不一致(以你的 Streamlit 版本官方说明为准),而且这类下限几乎必然随时间上移。
  • 安装细节属于「快照」:具体下载页面、按钮位置,出版后就会漂移;要装就去看当时的官方文档,别照书点。
  • 工作流一节假定你在本机开发。 远程开发环境(云 IDE、容器里写代码)的循环不一样, 这一章没有覆盖;第 12 章的 Docker 会部分补上「环境长什么样」的图景。
  • 虚拟环境只讲了「为什么」和「有哪些选择」,没有给完整操作流。 venv 的具体命令、 poetry 的用法都不在正文里——这是有意的留白,但对零基础读者来说可能正好卡在门口。
  • 「杀掉服务器」那一节的「CONNECTING」现象,是第 04 章执行模型最好的预告片; 如果当时觉得「为什么界面不能自己活着」,恭喜你——你已经摸到了那个问题。

判断(我们的,不是书里的): 这一章看起来是「安装教程」,实际上是全书 心智模型的第一次落地:界面 = 脚本的一次执行;按钮 = 这一次执行里的条件; 服务器 = 应用的本体。密码检查器之所以选得妙,是因为它小到可以完整装进脑子, 又恰好把三个模型全用上。相比之下,环境三件套是任何 Python 书都有的标准内容, 不是这本书的独特贡献。 如果错,会错在: 如果读者已经熟悉 Git/虚拟环境,这一章的增量几乎全在 第 5–6 节;把整章当必读对老手的性价比低——但它的存在是为「半技术读者」 这个明确受众服务的,这个取舍本身没有错。

9. 可带走的

  1. streamlit run app.py 启动的是服务器,终端窗口就是它的命;Ctrl-C = 杀服务器 = 浏览器里界面变灰。
  2. 开发循环的灵魂是 Rerun/Always Rerun:服务器常驻,你只是在反复「让它再跑一遍」。
  3. localhost:8501:localhost = 本机,8501 = 默认端口;局域网里别人可用 Network URL 访问。
  4. 界面元素按代码顺序出现;if st.button(...) 里没有回调,按钮状态就是这一轮运行里的布尔值。
  5. st.text_input(type="password") 遮蔽输入;st.success/st.error 是语义化颜色的消息框;st.write 是万能输出。
  6. 「规则表 = 字典,规则 = lambda」是组织检查逻辑的好样板:加规则就是加一行字典。
  7. Git 当时光机用,虚拟环境当隔离病房用——两个比喻背后的机制(提交历史 / 独立解释器)值得各花一小时搞实。
  8. 学习阶段用普通 IDE,别用 AI 代写——至少第一个应用要自己敲。
  9. 改了非 .py 的依赖(数据文件、库版本)而界面没变,第一反应是重启服务器。
  10. 浏览器打不开应用时的排查序:手动敲 Local URL → 升级浏览器 → 换 Chrome。

10. 原文地图

主题原书章原文位置
安装:Python 3.9+ 与 pip install streamlit2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:30搜「pip install streamlit」)
Git 是「代码的时光机」2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:46搜「time machine」)
学习阶段不建议 AI 优先工具2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:74搜「Codex」)
PyCharm / VS Code 对比2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:65搜「Code editors」)
虚拟环境解决依赖冲突2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:98搜「Virtual environments」)
streamlit hello 自带演示2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:394搜「streamlit hello」)
开发工作流九步(figure 2.4)2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:141搜「development workflow」)
密码检查器完整代码(listing 2.1)2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:260搜「Listing 2.1」)
lambda 与字典推导式解释2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:321搜「lambdas」)
st.button 放进 if 的第一处伏笔2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:354搜「some interesting nuances」)
localhost:8501 与 Network URL2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:404搜「Local URL」)
改代码后 Rerun / Always Rerun2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:456搜「Always Rerun」)
关闭服务器后的 CONNECTING 现象2 Getting started with Streamlittext/11-ch02-2-getting-started-with-streamlit.txt:484搜「CONNECTING」)
附录:查 Python 版本、-V 大写Appendix Installing Python and Streamlittext/22-apx-i-appendix-installing-python-and-streamlit.txt:27搜「case-sensitive」)

Footnotes

  1. 出处:「2 Getting started with Streamlit」第 17–21 段(text/11-ch02-2-getting-started-with-streamlit.txt:30,搜「pip install streamlit」)。原文:装 3.9+ 的 Python(作者推荐 3.11+),然后 pip install streamlit。 ↩

  2. 出处:「2 Getting started with Streamlit」第 22–26 段(text/11-ch02-2-getting-started-with-streamlit.txt:13,搜「three key workflow considerations」)。 ↩

  3. 出处:「2 Getting started with Streamlit」第 141–145 段(text/11-ch02-2-getting-started-with-streamlit.txt:142,搜「iterative process」)。 ↩

  4. 出处:「2 Getting started with Streamlit」第 196–199 段(text/11-ch02-2-getting-started-with-streamlit.txt:196,搜「Building your first app」)。 ↩

  5. 出处:「Appendix Installing Python and Streamlit」第 9–24 段(text/22-apx-i-appendix-installing-python-and-streamlit.txt:20,搜「python --version」)。「-V is case-sensitive」在该文件第 21 段。 ↩

  6. 出处:「2 Getting started with Streamlit」第 477–485 段(text/11-ch02-2-getting-started-with-streamlit.txt:479,搜「serves」)。原文:这个终端窗口就是 serve 你的应用的 Streamlit 服务器所在;Ctrl-C 关闭后按钮禁用、界面显示 CONNECTING。 ↩

  7. 出处:「2 Getting started with Streamlit」第 460–461 段(text/11-ch02-2-getting-started-with-streamlit.txt:460,搜「monitors your app file」)。 ↩

  8. 出处:「2 Getting started with Streamlit」第 410–414 段(text/11-ch02-2-getting-started-with-streamlit.txt:410,搜「localhost」)。原文解释 localhost 意为「你这台电脑」,端口可能是 8502 等。 ↩

  9. 出处:「2 Getting started with Streamlit」第 42–48 段(text/11-ch02-2-getting-started-with-streamlit.txt:46,搜「time machine for your code」)。 ↩

  10. 出处:「2 Getting started with Streamlit」第 49–56 段(text/11-ch02-2-getting-started-with-streamlit.txt:50,搜「go back in time」)。 ↩

  11. 出处:「2 Getting started with Streamlit」第 60–63 段(text/11-ch02-2-getting-started-with-streamlit.txt:62,搜「Atlassian」)。 ↩

  12. 出处:「2 Getting started with Streamlit」第 65–71 段(text/11-ch02-2-getting-started-with-streamlit.txt:68,搜「Integrated Development Environment」)。 ↩

  13. 出处:「2 Getting started with Streamlit」第 78–85 段(text/11-ch02-2-getting-started-with-streamlit.txt:84,搜「Community Edition」)。 ↩

  14. 出处:「2 Getting started with Streamlit」第 86–92 段(text/11-ch02-2-getting-started-with-streamlit.txt:89,搜「ecosystem of plugins」)。 ↩

  15. 出处:「2 Getting started with Streamlit」第 72–76 段(text/11-ch02-2-getting-started-with-streamlit.txt:73,搜「AI-first tools」)。原文:推荐学习过程中坚持用普通的非 AI IDE。 ↩

  16. 出处:「2 Getting started with Streamlit」第 98–103 段(text/11-ch02-2-getting-started-with-streamlit.txt:102,搜「updating a library for one project breaks another」)。 ↩

  17. 出处:「2 Getting started with Streamlit」第 108–111 段(text/11-ch02-2-getting-started-with-streamlit.txt:109,搜「isolated instance of Python」)。 ↩

  18. 出处:「2 Getting started with Streamlit」第 114–115 段(text/11-ch02-2-getting-started-with-streamlit.txt:115,搜「venv, pipenv, pyenv, poetry」)。 ↩

  19. 出处:「2 Getting started with Streamlit」第 23–25 段(text/11-ch02-2-getting-started-with-streamlit.txt:35,搜「largely a matter of preference」)。 ↩

  20. 出处:「2 Getting started with Streamlit」第 465–468 段(text/11-ch02-2-getting-started-with-streamlit.txt:466,搜「smoother development」)。 ↩

  21. 出处:「2 Getting started with Streamlit」第 473–475 段(text/11-ch02-2-getting-started-with-streamlit.txt:475,搜「Run on Save」)。 ↩

  22. 出处:「2 Getting started with Streamlit」第 191–194 段(text/11-ch02-2-getting-started-with-streamlit.txt:193,搜「shut down and restart」)。 ↩

  23. 出处:「2 Getting started with Streamlit」第 297–303 段(text/11-ch02-2-getting-started-with-streamlit.txt:298,搜「st to refer to it」)。 ↩

  24. 出处:「2 Getting started with Streamlit」第 319–324 段(text/11-ch02-2-getting-started-with-streamlit.txt:321,搜「anonymous inline functions」)。 ↩

  25. 出处:「2 Getting started with Streamlit」第 328–337 段(text/11-ch02-2-getting-started-with-streamlit.txt:336,搜「dictionary comprehension」)。 ↩

  26. 出处:「2 Getting started with Streamlit」第 343–348 段(text/11-ch02-2-getting-started-with-streamlit.txt:347,搜「toggle to show or hide」)。 ↩

  27. 出处:「2 Getting started with Streamlit」第 349–355 段(text/11-ch02-2-getting-started-with-streamlit.txt:354,搜「interesting nuances」)。原文预告:这里有些微妙的细节,第 4 章再深入。 ↩

  28. 出处:「2 Getting started with Streamlit」第 370–375 段(text/11-ch02-2-getting-started-with-streamlit.txt:374,搜「semantic styles」)。原文:st.success 和 st.error 是带语义样式的文本容器,大体是绿框和红框。 ↩

  29. 出处:「2 Getting started with Streamlit」第 376–382 段(text/11-ch02-2-getting-started-with-streamlit.txt:379,搜「Please enter a password」)。 ↩

  30. 出处:「2 Getting started with Streamlit」第 384–398 段(text/11-ch02-2-getting-started-with-streamlit.txt:388,搜「streamlit run <filename>」)。 ↩

  31. 出处:「2 Getting started with Streamlit」第 419–427 段(text/11-ch02-2-getting-started-with-streamlit.txt:419,搜「Troubleshooting streamlit run」)。 ↩

  32. 出处:「2 Getting started with Streamlit」第 429–433 段(text/11-ch02-2-getting-started-with-streamlit.txt:430,搜「at least one numeral」)。 ↩

  33. 出处:「2 Getting started with Streamlit」第 454–458 段(text/11-ch02-2-getting-started-with-streamlit.txt:455,搜「source file has changed」)。 ↩

  34. 出处:「2 Getting started with Streamlit」第 434–447 段(text/11-ch02-2-getting-started-with-streamlit.txt:434,搜「Listing 2.2」)。 ↩

  35. 出处:「2 Getting started with Streamlit」第 483–485 段(text/11-ch02-2-getting-started-with-streamlit.txt:484,搜「CONNECTING」)。 ↩

  36. 出处:「2 Getting started with Streamlit」第 486–490 段(text/11-ch02-2-getting-started-with-streamlit.txt:487,搜「re-establishes the connection」)。 ↩

  37. 出处:「2 Getting started with Streamlit」第 72–76 段(text/11-ch02-2-getting-started-with-streamlit.txt:75,搜「incredibly powerful in day-to-day use」)。 ↩

  38. 出处:「2 Getting started with Streamlit」第 163–170 段(text/11-ch02-2-getting-started-with-streamlit.txt:35,搜「matter of preference」)。 ↩

  39. 出处:「2 Getting started with Streamlit」第 18–20 段(text/11-ch02-2-getting-started-with-streamlit.txt:28,搜「3.11」)。 ↩

  40. 出处:「Appendix Installing Python and Streamlit」第 9–10 段(text/22-apx-i-appendix-installing-python-and-streamlit.txt:15,搜「3.10 and above」)。 ↩

On this page