hug:写 Python API,几行代码就够了
Python 生态里做 API 框架的选择不少,Flask、FastAPI、Django REST Framework 各有各的拥趸。hug 的定位有点不一样,它的设计目标是把"定义一个 API"这件事做到跟"写一个函数"一样简洁。项目目前在 GitHub 上有 6,886 个 Star。

函数即 API
hug 最核心的机制是 METHOD 装饰器。给一个普通 Python 函数加上 @hug.get(),它就直接变成一个 HTTP API 端点,函数原来的行为完全不受影响。
python
@hug.get('/happy_birthday')
def happy_birthday(name, age: hug.types.number = 1):
return "Happy {age} Birthday {name}!".format(**locals())
然后 hug -f happy_birthday.py 一行命令启动服务,浏览器就能调用了。API 文档自动生成在 /documentation 路径,不需要额外写 OpenAPI 配置。
这种装饰器不修改原函数的设计带来了一个实际好处:测试逻辑可以直接调用原函数。hug 提供了 hug.test 模块,hug.test.get(module, 'endpoint', {'name': 'Timothy', 'age': 25}) 就能拿到 Response 对象做断言,全程不需要启动服务器。对习惯写单元测试的团队来说,这个体验比需要起测试客户端的框架顺畅不少。
类型注解驱动参数校验
hug 大量依赖 Python 3 的类型注解来完成参数校验和类型转换。函数参数后面标注 :int,hug 自动把请求参数转成整型,不合法输入直接报错。更复杂的场景可以接入 marshmallow 的 fields 类型。
类型注解同时喂给了自动文档系统,API 调用方一眼就能看到每个参数期望什么类型。参数多了以后,不用来回翻文档确认字段类型,省了不少沟通成本。
HTTP 和 CLI 共用一套代码
hug 的同一个装饰器函数同时支持 HTTP 和 CLI 两种调用方式。调试的时候可以在命令行直接跑函数,确认逻辑没问题再切回 HTTP 模式。一套代码、两个入口,运维脚本和 Web 接口可以复用同一个函数。
版本管理也内置了。同一个路径 /echo 可以分别注册 v1 和 v2,hug 自动根据 URL 前缀或请求头路由到对应版本:
python
@hug.get('/echo', versions=1)
def echo(text):
return text
@hug.get('/echo', versions=range(2, 5))
def echo(text):
return "Echo: {text}".format(**locals())
多文件项目通过 hug.extend_api() 或 hug.API(__name__).extend() 把不同模块的端点挂载到不同路由前缀,大型项目组织起来也没什么障碍。
底层基于 Falcon
hug 构建在 Falcon 这个高性能 WSGI 库之上,天然兼容 uWSGI、Gunicorn 等 WSGI 服务器。项目提供了 Docker Compose 配置,可以一键启动 Gunicorn 容器部署。同时支持 asyncio 协程语法,但由于 Falcon 本身是同步服务器,实际请求处理仍然是同步的,对异步并发有强需求的场景需要留意这一点。
输出格式方面,hug 支持 JSON 之外的自定义 Formatter,也可以根据请求的 Content-Type 切换 Input Formatter。中间件机制兼容 Falcon 原生中间件,权限校验、请求日志都能直接挂进去。

适合什么场景
hug 的定位跟 FastAPI 有重叠,但不完全一样。hug 更强调"极简定义",适合中小型 API 项目、内部工具接口、或者想快速把 Python 函数暴露成 HTTP 服务的场景。如果项目已经有复杂的中间件层级和依赖注入需求,FastAPI 是更成熟的选择。但如果追求少写代码、快速上线,hug 的设计方向值得一试。
hug 的全称是 Hopefully Useful Guide,项目从一开始就把自己定位为"指南型框架",希望通过自身的设计引导开发者写出结构清晰、自文档化的 API。这个思路在当时 FastAPI 还没出现的年代挺超前,6,886 个 Star 也说明它确实解决了一部分开发者的实际需求。