前言
「用 Python 写网页」这句话,不同的人理解差别很大。一种理解是「用 Python 生成 HTML」,那还是得懂标签、懂表单、懂一点点前端;另一种理解是「我只会写 Python 函数,但我想让别人在浏览器里点几下、看到结果」。PyWebIO 走的是后一条路。
先说清楚它的定位,避免用错场景:PyWebIO 是一个第三方库,需要单独安装,它把浏览器当成一个「输入输出终端」,你用input()那样的函数拿数据、用put_text()那样的函数显示结果,交互流程按你写代码的顺序推进。它适合内部小工具、报表、数据核对脚本的快速上线,不适合做面向公众的正式站点——没有 SEO 意义上的页面结构,也不适合承载复杂的页面布局和前端交互。
还要纠正一个常见说法:把 PyWebIO 说成「不用写任何代码就能做网站」是不准确的。你依然要写代码,只是写的是顺序执行的 Python 代码,而不是 HTML/JS/CSS 三件套。它的价值在于把「做一个有输入框、有按钮、有结果的页面」这件事,从跨技术栈的问题变成了写函数的问题。
本文讲清楚三件事:它的核心想法是什么、输入输出控件怎么写、什么时候该用它、什么时候不该用。文中涉及的具体接口签名以 PyWebIO 官方文档为准,版本差异也请以官方文档为准。
一、核心想法:把网页交互写成顺序执行的脚本
传统网页开发是「事件驱动」的:你绑定一个回调,用户点按钮时回调被触发,你要自己管理「现在页面处于哪种状态」。
PyWebIO 换了个模型:你的函数从头到尾顺序执行,遇到输入函数就停下来等用户输入,拿到值之后继续往下走。这就是它最像命令行程序的地方——整个交互流程就是你代码的缩进顺序。
你的函数开始
↓
input("请输入姓名") ← 浏览器显示一个输入框,函数在这里等
↓(用户填完点提交)
拿到 name 变量
↓
put_text("你好," + name) ← 浏览器显示一行文字
↓
函数结束这样做的好处是,一个原本要用「表单提交 + 后端路由 + 状态管理」才能完成的小工具,现在就是一个带几个缩进层级的函数。代价是它不适合做「页面上有十几个互相关联的控件、每改一个就局部刷新」这种复杂界面。
二、输入、输出与按钮
输入控件
输入类函数都在pywebio.input下,共同点是调用即阻塞,返回值就是用户填的内容。
# 适用于 Python 3.8+;需先安装 PyWebIO,接口以官方文档为准
from pywebio.input import input, select, checkbox, radio, textarea, NUMBER
name = input("请输入姓名")
age = input("请输入年龄", type=NUMBER) # NUMBER 让返回值是数字
city = select("所在城市", options=["北京", "上海", "广州"])
hobbies = checkbox("兴趣爱好", options=["读书", "跑步", "音乐"]) # 返回列表
level = radio("熟练程度", options=["入门", "熟练"])
remark = textarea("备注", rows=3)几个要点:
input()的type决定控件形态与返回值类型。默认是TEXT(字符串);传NUMBER时返回数字;其它类型常量请对照官方文档。select默认是单选,返回选中的那一项;multiple=True时返回列表。checkbox返回的是列表,radio返回的是单个值,不要搞反。- 所有输入函数都支持
validate参数,传一个函数进去做校验,返回错误字符串表示校验不通过、页面会提示。
# 适用于 Python 3.8+;需先安装 PyWebIO,接口以官方文档为准
from pywebio.input import input, NUMBER
def check_age(value):
if value < 0 or value > 150:
return "年龄要在 0 到 150 之间"
return None
age = input("年龄", type=NUMBER, validate=check_age)validate返回None表示通过,返回字符串则把这句话显示给用户。校验逻辑放在这里,比拿到值之后再自己判断要友好得多——页面不会因为一个不合法的输入就整个中断。
输出控件
输出类函数都在pywebio.output下,顾名思义都是往页面上「放」东西。
# 适用于 Python 3.8+;需先安装 PyWebIO,接口以官方文档为准
from pywebio.output import put_text, put_markdown, put_table, put_success
put_text("处理完成") # 普通文本
put_markdown("## 统计结果\n\n共 3 条记录") # 渲染 Markdown
put_table([
["姓名", "分数"],
["小明", 92],
["小红", 88],
])
put_success("全部通过")put_table接收一个二维列表,第一行可以当表头。单元格里也可以放别的输出对象,比如put_markdown(...)的返回值,这在要做「表格里带链接/加粗」时很有用。
按钮
按钮用put_buttons输出,并绑定一个点击回调:
# 适用于 Python 3.8+;需先安装 PyWebIO,接口以官方文档为准
from pywebio.output import put_buttons, put_text
def on_click(choice):
put_text("你点了:" + choice)
put_buttons(["确认", "取消"], onclick=on_click)buttons是按钮列表,onclick是回调函数,回调会收到被点击按钮对应的值。注意:输出函数是往里放内容,不会阻塞。如果你需要「等用户点一下再继续」,用的是pywebio.input.actions,那才是一个阻塞的输入函数。
三、把它跑起来
写完之后,用一个启动函数把应用挂到本地端口上。PyWebIO 支持多种后端,默认的启动方式就够用了:
# 适用于 Python 3.8+;需先安装 PyWebIO,接口以官方文档为准
from pywebio import start_server
def main():
name = input("请输入姓名")
put_text("你好," + name)
if __name__ == "__main__":
start_server(main, port=8080, debug=True)启动后浏览器打开本机 8080 端口就能看到页面。port参数建议显式传,不要依赖默认值——不同后端的默认端口并不一致,这一点对照官方文档最稳妥。
四、什么时候该用、什么时候不该用
| 场景 | 适合 PyWebIO 吗 | 原因 |
|---|
| 给同事写个数据查询小工具 | 适合 | 输入 → 查询 → 展示结果,一条直线 |
| 把一段分析脚本变成网页 | 适合 | 不用重构逻辑,加几个输入输出即可 |
| 生成一份可交互的报表 | 适合 | put_table直接出表,够用 |
| 面向公众的官网、博客 | 不适合 | 缺少页面结构与 SEO 所需的静态化能力 |
| 复杂的前端交互与动画 | 不适合 | 顺序执行模型天然不擅长频繁的局部更新 |
| 高并发对外服务 | 不适合 | 定位是内部工具,部署与安全加固要另想办法 |
一句话总结选型:你的交互流程能用一条「从上到下」的流程图描述清楚,就用它;一旦流程图里出现大量往回指的箭头,就该换方案了。
常见坑点
1. 把checkbox的返回值当字符串用
❌if checkbox("爱好", options=["读书"]): ...然后拿去做字符串拼接。 ✅checkbox返回列表(比如["读书"]),拼接时要", ".join(hobbies)。
2. 以为put_buttons会阻塞等待
❌put_buttons(["确认"], onclick=cb)之后立刻假设用户已经点过了。 ✅put_buttons只是把按钮画上去,不阻塞;需要「等点击」请用pywebio.input.actions。
3. 把校验写在拿到值之后
❌ 先input("年龄"),再用if判断、手动抛异常中断整个流程。 ✅ 用validate参数,返回错误字符串让页面就地提示,流程不中断。
4. 忘记安装依赖
❌ 直接from pywebio.input import input,报模块找不到。 ✅ PyWebIO 是第三方库,先按官方文档安装,再运行脚本。
5. 用它做面向公众的正式站点
❌ 把 PyWebIO 应用当作官网主站对外发布。 ✅ 它定位是内部小工具;正式站点请用常规 Web 框架,配套模板、静态资源与安全配置。
6. 依赖默认端口
❌start_server(main)不传port,换了后端就不知道访问哪个端口。 ✅ 显式写start_server(main, port=8080),并核对官方文档里该后端支持的参数。
7. 拿input的返回值直接当数字运算
❌age = input("年龄")之后写age + 1,字符串加整数直接报错。 ✅ 声明type=NUMBER,或自己显式转换并处理转换失败的输入。
8. 在输出里拼 HTML 字符串
❌ 为了让文字加粗,在put_text里塞标签字符串。 ✅ 用put_markdown("**加粗**")表达富文本;要输出原生 HTML 用put_html,并意识到它不会做转义处理。
总结
| 概念 | 一句话记住 |
|---|
| 执行模型 | 函数顺序执行,遇到输入函数就阻塞等用户 |
| 输入 | pywebio.input下的函数,返回值即用户输入 |
| 输出 | pywebio.output下的put_xxx,调用即上屏、不阻塞 |
| 按钮 | put_buttons绑定回调;要阻塞等待用actions |
| 定位 | 内部工具、报表、脚本网页化,不是公众站点 |
PyWebIO 的初体验往往很顺:把一个已有的 Python 脚本加几行输入输出,十分钟就能变成一个别人点得动的网页。但请记住它的边界——它是「把脚本搬上网页」的捷径,不是「做网站」的替代品。选型时先问自己交互流程是不是一条直线,答案就清楚了。