Bottle 框架快速上手:Python 轻量级 WSGI 微框架从安装到路由实战
Bottle 框架快速上手:Python 轻量级 WSGI 微框架从安装到路由实战
Bottle 是一个以单一 bottle.py 文件分发、除 Python 标准库外零依赖的轻量级 WSGI 微框架,本指南以其官方文档 docs/index.rst 为骨架,结合当前仓库源码带你掌握路由映射、模板渲染、内置服务器启动、安装部署方式以及文档体系导航,读完即可用几行代码跑起一个可访问的 Web 应用。
框架概览:为什么选择 Bottle
Bottle 定位是 "fast, simple and lightweight",它把 Web 开发中最常用的能力压缩进一个单文件模块 bottle.py(约 4500 行)中,核心特性集中在四个方面:
- 路由(Routing):将 HTTP 请求映射到 Python 函数,支持整洁的动态 URL(如
/hello/<name>),由 bottle.py 中的 Router 类 实现,底层将路由规则编译为正则表达式进行匹配。 - 模板(Templates):自带快速且 Pythonic 的内置模板引擎(SimpleTemplate,详见 docs/stpl.rst),同时支持 Mako、Jinja2、Cheetah 等第三方模板引擎。
- 工具(Utilities):提供对表单数据、文件上传、Cookie、请求头等 HTTP 特性的便捷访问,全部封装在 BaseRequest 类 中。
- 服务器(Server):内置 HTTP 开发服务器,并提供面向 gunicorn、paste、cheroot 等众多 WSGI 服务器的现成适配器,详见 docs/deployment.rst。
由于整个框架就是一个模块文件,你可以直接把它拷贝进项目目录使用,也可以作为标准 WSGI 应用挂载到任何 WSGI 兼容的环境中。
一分钟上手:"Hello World" 示例
官方文档给出的入门示例展示了 Bottle 的三个核心 API——route 装饰器、template 函数和 run 启动器:
from bottle import route, run, template
@route('/hello/<name>')
def index(name):
return template('<b>Hello {{name}}</b>!', name=name)
run(host='localhost', port=8080)
把这段代码保存为脚本运行,或直接粘贴进 Python 交互式控制台,然后访问 http://localhost:8080/hello/world 即可看到渲染结果。
它的工作原理值得拆解:
@route('/hello/<name>')把/hello/<name>这个 URL 路径绑定到index函数,<name>是通配符,URL 中对应片段会作为关键字参数name传入函数。template(...)调用内置模板引擎,将{{name}}占位符替换为传入的值并渲染出 HTML。run(host='localhost', port=8080)启动内置开发服务器,阻塞运行直到按 Ctrl-C 停止。
从源码看,run 函数的完整签名(bottle.py#L3800)默认使用 wsgiref 服务器适配器、绑定 127.0.0.1:8080,开发期无需任何额外配置即可运行。
安装与获取:三种方式对比
官方文档明确说明 Bottle 除 Python 标准库外没有硬性依赖(模板或服务器适配器类需要对应模块时才需要额外安装)。
方式一:pip 安装稳定版(推荐)
pip install bottle
方式二:直接下载单文件
把 bottle.py 下载到项目目录即可使用,无需安装:
wget https://bottlepy.org/bottle.py
方式三:配合虚拟环境使用
更推荐为每个项目创建独立虚拟环境再安装:
python3 -m venv venv # 创建虚拟环境
source venv/bin/activate # 切换默认 Python 到虚拟环境
pip install -U bottle # 在虚拟环境中安装 bottle
此外,Bottle 既是模块也是命令行程序。通过 pip 安装后,路径上会出现 bottle 命令,可用于启动应用(详见 docs/tutorial.rst):
bottle --help
python3 -m bottle --help
./path/to/bottle.py --help
示例(使用 --debug 与 --reload 启动模块 mymodule):
bottle --debug --reload mymodule
输出类似:
Bottle v0.13-dev server starting up (using WSGIRefServer())...
Listening on http://localhost:8080/
Hit Ctrl-C to quit.
注意:0.13 版本起,可执行脚本从 bottle.py 更名为 bottle,旧名称已弃用,以避免循环导入问题。
Python 版本支持矩阵("Dead Snakes" 策略)
Bottle 0.12 及之前版本支持了极为宽泛的 Python 版本(其中一些早已停止维护超过十年)。自 0.13 起,项目只保证与仍在官方维护周期内的 Python 版本保持向后兼容;旧版本 Python 可能仍能运行,但不再经过兼容性测试。
官方文档中的支持矩阵如下:
| Bottle 版本 | Python 2 | Python 3 |
|---|---|---|
| 0.12 | 2.5 - 2.7 | 3.2 - 3.12 |
| 0.13 | 2.7 | >=3.8 |
| 0.14(规划中) | 已放弃 | >=3.9 |
文档脚注进一步说明:Bottle 通常仍能在刚停止维护的 Python 3.x 版本上运行,项目不会刻意破坏兼容性,但也不再针对这些版本进行测试,使用时需自行承担风险。如果你的生产环境必须依赖较老的 "dead snakes" Python,建议停留在 Bottle 0.12(长期支持版);否则应定期升级以获取新功能与改进。
四大核心能力详解
结合文档路标与源码,下面深入每一项核心能力。
1. 路由:从静态路径到动态 URL
路由是 Bottle 最重要的概念。route 装饰器将 URL 路径与回调函数绑定,一个回调可以绑定多个路由,动态路由中的通配符会以关键字参数形式传入函数:
@route('/')
@route('/hello/<name>')
def greet(name='Stranger'):
return template('Hello {{name}}, how are you?', name=name)
通配符语法为 <name>,默认匹配到下一个斜杠为止;通过过滤器可约束和转换匹配内容(详见 docs/routing.rst)。内置过滤器对应源码 Router.filters 中的实现:
| 过滤器 | 匹配规则 | 说明 |
|---|---|---|
:int |
有符号数字,转换为 int |
对应正则 -?\d+ |
:float |
小数,转换为 float |
对应正则 -?[\d.]+ |
:path |
非贪婪匹配任意字符(含 /) |
可匹配多段路径,对应正则 .+? |
:re |
在配置字段中指定自定义正则 | 匹配值不经过类型转换 |
实战示例:
@route('/object/<id:int>')
def callback(id):
assert isinstance(id, int)
@route('/show/<name:re:[a-z]+>')
def callback(name):
assert name.isalpha()
@route('/static/<path:path>')
def callback(path):
return static_file(path, ...)
2. HTTP 方法与头部处理
所有未指定方法的路由默认只匹配 GET 请求。处理 POST、PUT、DELETE、PATCH 时,可在 route 装饰器中传 method 参数,或直接使用 get、post、put、delete、patch 五个快捷装饰器(见 bottle.py#L898-L916)。
表单登录示例:
from bottle import get, post, request
@get('/login') # 显示表单
def login():
return '''
<form action="/login" method="POST">
Username: <input name="username" type="text" />
Password: <input name="password" type="password" />
<input value="Login" type="submit" />
</form>
'''
@post('/login') # 处理提交
def do_login():
username = request.forms.username
password = request.forms.password
if check_login(username, password):
return "<p>Your login information was correct.</p>"
else:
return "<p>Login failed.</p>"
此外有两个特殊方法值得注意:
- HEAD:自动回退到对应的 GET 路由并截断响应体,用于获取资源的元信息,无需手动声明 HEAD 路由。
- ANY:非标准方法,作为低优先级兜底——
ANY路由会匹配任意 HTTP 方法,但仅当没有更具体的匹配路由时生效,非常适合代理路由(proxy-route)场景。
从源码看,Bottle 实例本身就是一个可调用的 WSGI 应用(__call__ 委托给 wsgi 方法,见 bottle.py#L1091-L1093),_handle 负责执行路由匹配与回调调用。
3. 模板:内置引擎与第三方支持
Bottle 自带 SimpleTemplate 引擎,支持 {{...}} 变量插值、% 行内 Python 代码等语法,详细教程见 docs/stpl.rst。同时通过适配器支持 Mako、Jinja2 和 Cheetah 模板,模板引擎的插件化加载实现在 TemplatePlugin 类。
4. 服务器:内置开发服务器与生产部署适配
开发期用 run() 即可;生产部署时 Bottle 提供大量 WSGI 服务器适配器(gunicorn、paste、cheroot、bjoern、flup 等),配置方式见 docs/deployment.rst。run 的关键参数(源码签名见 bottle.py#L3800-L3809):
| 参数 | 默认值 | 说明 |
|---|---|---|
host |
127.0.0.1 |
绑定地址;传 0.0.0.0 监听所有网络接口 |
port |
8080 |
端口;低于 1024 需要 root 权限 |
server |
wsgiref |
服务器适配器名称或 ServerAdapter 子类 |
reloader |
False |
是否启用自动重载 |
interval |
1 |
自动重载检查间隔(秒) |
quiet |
False |
是否抑制输出 |
debug |
None |
调试模式开关 |
文档导航:官方文档体系与进阶路线
官方文档索引把全部文档按五个主题组织,每篇对应一个进阶方向。以下均为当前仓库 docs/ 目录下的真实文件,可作为持续学习的地图:
入门篇(Getting Started)
- docs/tutorial.rst —— 用户指南,从 Hello World 到请求数据、Cookie、会话的完整实战教程
- docs/api.rst —— 自动生成的完整 API 参考
- docs/changelog.rst —— 版本变更日志
- docs/faq.rst —— 常见问题解答
进阶主题(Advanced Topics)
- docs/routing.rst —— 路由匹配规则、过滤器自定义与 URL 构建
- docs/configuration.rst —— 应用配置系统(ConfigDict)
- docs/stpl.rst —— SimpleTemplate 模板引擎语法详解
- docs/deployment.rst —— 多服务器部署、负载均衡与反向代理
- docs/async.rst —— 异步与并发主题
插件(Plugins)
- docs/plugins/index.rst —— 插件概览
- docs/plugins/dev.rst —— 插件开发指南
- docs/plugins/list.rst —— 插件列表
补充与开发
- docs/tutorial_app.rst —— 一个完整的应用教程(Todo 清单示例)
- docs/development.rst —— 项目开发贡献指南
- docs/contributors.rst —— 贡献者名单
其中,路由、配置、模板引擎与部署四篇是进阶到生产级应用必读的核心材料。
从源码看框架核心实现
为进一步印证文档描述,当前仓库的 bottle.py 提供了全部实现证据:
- 请求处理链路:
Bottle.wsgi()(bottle.py#L1059)是 WSGI 入口,内部先调用_handle(environ)完成路由匹配与回调执行,再通过_cast(bottle.py#L984)对回调返回值进行类型归一化,最后调用 WSGI 的start_response输出。catchall配置为True时,未捕获异常会转为 500 错误页而不会击垮 WSGI 服务器。 - 动态路由编译:
Router.add()(bottle.py#L329)把通配符规则编译成带命名分组((?P<name>...))的正则表达式;静态路由单独存入self.static字典优先匹配,动态路由存入self.dyna_routes。CPython 正则单次最多支持 99 个分组,源码中_MAX_GROUPS_PER_PATTERN = 99(bottle.py#L278)对此做了显式限制。 - 核心插件机制:每个
Bottle实例在初始化时自动安装JSONPlugin与TemplatePlugin(bottle.py#L630-L631)——这正是"返回字典自动转为 JSON 响应""模板自动渲染"两个开箱即用行为的来源。 - Hook 机制:支持
before_request、after_request、app_reset、config四类钩子(bottle.py#L636),其中after_request按逆序执行,便于在响应阶段做统一加工。
许可与使用须知
Bottle 的代码与文档以 MIT 许可证发布,许可证全文见仓库根目录 LICENSE。但有一个重要例外:Bottle 的 Logo 不受该许可证覆盖——Logo 仅允许用于指向 Bottle 主页的链接,或与未修改的库直接相关的情境;其他情况使用前需先征求许可。
结语
从本文可以看出,Bottle 的价值在于"小而不薄":单文件、零依赖让上手成本几乎为零,而路由过滤器、内置模板引擎、插件机制、WSGI 兼容性等设计又保证了它足以支撑真实项目。建议按本文的文档地图,结合 bottle.py 源码逐篇深入,尤其是 docs/tutorial.rst 的完整教程与 docs/routing.rst 的动态路由进阶,即可从"能跑通"走向"用得精"。