Lihil, Python下一代高性能企业级后端开发框架
Lihil 是一个具备极高性能的 Python Web 框架,[^1],并且坚持"自带电池"的理念,开箱即用。

在我们的性能测试基准中,Lihil 的性能领先于所有其他已知的 ASGI 框架, 包括(BlackSheep, robyn, sanic, fastapi, etc.)。
Lihil 实现并大幅改良了 FastAPI 的几乎所有核心特性,同时保持了对 Starlette / FastAPI 大部分组件的兼容支持(如 Request、Response、中间件等)。在此基础上,Lihil 引入了一个强大且易用的插件系统,并内置了一系列开箱即用的企业级插件,包括但不限于:
- 用户认证与权限管理
- API 端口级限流
- 分布式消息事件分发系统
- 多数据库集成支持
这些内置能力大幅减少了重复造轮子的工作,让开发者可以专注于业务本身。
Hello, World
python
from lihil import Lihil, Text, Annotated
lhl = Lihil()
@lhl.get
def hello(world: str = "world") -> Annotated[Text, 200]:
return f"hello, {world}!"
一个最小的 "Hello World" 示例仅需几行代码即可启动,并且默认带有类型校验、文档生成、和响应类型约束。
Lihil 的特性
自动生成 OpenAPI 文档
Lihil 提供了 OpenAPI 与 Swagger UI,能自动根据端点函数的参数与返回值生成文档 ,同时集成了接口调试工具和测试框架,方便开发与测试。
除此之外,Lihil 还具备对异常的结构化处理能力:当你自定义 HTTPException 的子类时,框架会自动将其转换为符合 RFC9457 的结构化 ErrorResponse,从而帮助前端更好地理解错误语义与处理错误逻辑。
例如,假设我们定义如下业务错误:
python
from lihil import HTTPException
class OutOfStockError(HTTPException[str]):
"The order can't be placed because items are out of stock"
__status__ = 422
def __init__(self, order: Order):
detail: str = f"{order} can't be placed, because {order.items} is short in quantity"
super().__init__(detail)
然后在接口中抛出该错误:
python
@orders.post
async def place_order(order_id: str, order_repo: Annotated[OrderRepo, use(OrderRepo)]):
order = await order_repo.get(order_id)
if not products.quantity:
raise OutOfStockError(order)
当客户端发出非法请求时,Lihil 会自动将 OutOfStockError 转换为如下结构的 ErrorResponse,无需任何额外配置:
json
{
"type": "out_of_stock_error",
"title": "The order can't be placed because items are out of stock",
"status": 422,
"detail": "order#123 can't be placed, because ['item#abc'] is short in quantity",
"instance": "users/ben/orders/43"
}
当用户请求错误时, Lihil会自动把OutOfStockError的示例转换为一个ErrorResponse:

这种做法不仅符合标准,也让业务异常结构更清晰、更容易被前端捕获与处理。
Problem Page
此外,Lihil 还会自动为所有用户自定义的错误生成一个详细的 Problem Page 网页文档。
该文档不仅帮助调用方理解"如何正确请求某个端点",还清晰列出该端点在不同业务场景下可能返回的所有错误类型及格式,极大降低了开发过程中后端与前端、服务提供方与调用方之间的沟通成本。

更强大、更灵活的依赖注入系统
Lihil 拥有一个基于类型的、高效且灵活的依赖注入系统,不仅实现了 FastAPI 所有的 DI 功能,更在多个方面做了显著改进:
-
依赖注入与框架解耦 :
你可以在端点定义中使用依赖注入,也可以在应用的任何位置自由使用,不再受限于框架内部结构。
-
基于类型的注入:一次定义,处处可用
无需在每个端点重复书写
Annotated[Engine, Depends(get_engine)](当然,你仍然可以这样做),你只需集中定义依赖,Lihil 会根据类型自动解析。例如:
python
from lihil import use, Ignore, Route
from typing import Annotated, NewType
from sqlalchemy.ext.asyncio import AsyncConnection, AsyncEngine
from uuid import uuid4
users = Route("users")
async def get_conn(engine: AsyncEngine) -> AsyncConnection:
async with engine.begin() as conn:
yield conn
UserID = NewType("UserID", str)
def user_id_factory() -> UserID:
return UserID(str(uuid4()))
@users.post
async def create_user(
user: UserData, user_id: UserID, conn: AsyncConnection
) -> Annotated[UserDB, status.Created]:
sql = user_sql(user=user, id_=user_id)
await conn.execute(sql)
return UserDB.from_user(user, id=user_id)
users.factory(get_conn)
users.factory(user_id_factory, reuse=False)
通过 users.factory(get_conn),Lihil 会在该路由下的所有端点中自动使用 get_conn 来解析 AsyncConnection 类型的参数。这种机制可以显著减少模板代码,让开发者聚焦业务本身。
- 支持无限嵌套的资源作用域(Scope)
Lihil 的依赖注入系统基于一个图结构,可以支持任意深度的作用域嵌套,帮助你构建精细的生命周期控制体系:
python
from lihil import Graph
dg = Graph()
async with dg.ascope(app_name) as app_scope:
async with dg.ascope(router_name) as router_scope:
async with dg.ascope(endpoint_name) as endpoint_scope:
async with dg.ascope(user_id) as user_scope:
async with dg.ascope(request_id) as request_scope:
...
你可以在不同的 Scope 中注册/替换依赖项,灵活应对测试、分层模块设计、多租户系统等复杂场景。
ididi(lihil的依赖注入框架)还有更多强大的功能,详细说明请参见文档:📘 lihil-ididi
Lihil 的创新不仅限于依赖注入。我们的目标之一,是像 Django 一样提供强大、开箱即用的插件体系,帮助开发者摆脱重复模板代码的束缚,专注于业务功能的实现。
接下来,让我们看看 Lihil 所提供的一些独特功能。
开箱即用的企业级开发插件
Lihil 提供了一系列内置插件,覆盖企业后端开发的核心需求。这些插件经过高度集成设计,可直接使用、可深度定制、可灵活替换,让你在快速开发与长期演进之间取得良好平衡。
用户鉴权
Lihil 同时支持两类用户鉴权方式:
- 适合初创项目或个人开发者的0成本开箱即用方案
- 面向中大型项目、具备高可扩展性与自定义能力的插件接口
集成 Supabase Auth:0 运维上线鉴权系统
借助 Supabase 提供的云原生用户系统,Lihil 可让你无需部署任何数据库 、无需编写用户表结构,就能通过两行代码实现注册和登录功能:
python
from lihil.plugins.auth.supabase import signin_route_factory, signup_route_factory
lhl = Lihil(
signin_route_factory(route_path="/login"),
signup_route_factory(route_path="/signup")
)
这两行代码将会:
- 自动添加
/login和/signup两个端口(可自定义路径) - 自动生成并集成至 OpenAPI 文档,方便调试与前端集成
- 支持配置用户凭证类型(邮箱、手机号、Token等)
为什么选择 Supabase?
- 无需本地数据库:用户信息全部托管在 Supabase 上,节省数据库配置与运维成本。
- 自带管理后台:通过 Supabase 提供的 Web 控制台,你可以方便地管理用户数据、查看登录记录、修改字段等。
- 高性价比 :Supabase 提供大量免费额度,结合将 Python 服务部署在 Cloudflare 等平台,整个应用可以零成本运行上线(俗称白嫖)。
无论你是想快速上线一个 side project,还是要构建一个可扩展的认证系统,Lihil 都为你提供了最适合的路径。
HTTP 鉴权:JWTAuthPlugin
当你已有现成的用户数据库,并希望使用JWT(JSON Web Token)来进行身份验证与会话管理时,Lihil 提供了 JWTAuthPlugin,帮助你快速完成 JWT 的 签发 、解析与参数注入,并与标准的 OAuth2 密码模式无缝集成(可以在Swagger UI直接调试)。
核心组件
JWTAuthPlugin:负责 JWT 的签发 (encode_plugin) 与解析 (decode_plugin)JWTAuthParam:用于注入解析后的 PayloadOAuth2PasswordFlow&OAuthLoginForm:实现 OAuth2 密码授权模式
使用步骤
-
初始化插件
pythonfrom lihil.plugins.auth.jwt import JWTAuthPlugin jwt_auth_plugin = JWTAuthPlugin( jwt_secret="mysecret", # 用于签名的密钥 jwt_algorithms="HS256" # 签名算法 ) -
定义 Payload 结构
你可以使用dataclasses.dataclass, typing.TypedDict或msgspec.Struct来定义一个payload结构体,
其中 field(name="sub")的字段将会被作为sub声明,而其他字段会作为自定义声明。
python
from lihil import Struct, field
from typing import Literal
class UserProfile(Struct):
user_id: str = field(name="sub") # 对应 JWT 的 "sub" 声明
role: Literal["admin", "user"] = "user" # 自定义声明
Token payload不一定要是一个结构体。更多时候我们会直接返回一个string(比如说user_id),返回的string 会用作JWT的"sub"声明。
-
解析 Token 并注入到端点
用户登陆后服务器返回token, 前端接受并保持,在需要的时候携带token访问接口通过token获取用户权限
pythonfrom lihil import Route, Annotated from lihil.plugins.auth.jwt import JWTAuthParam from lihil.plugins.auth.oauth import OAuth2PasswordFlow me = Route("/me") @me.get( auth_scheme=OAuth2PasswordFlow(token_url="token"), plugins=[jwt_auth_plugin.decode_plugin] ) async def get_user( profile: Annotated[UserProfile, JWTAuthParam], # 直接获得解析后的 UserProfile repo: UserRepo ) -> PublicUser: user_db = await repo.get(profile.user_id) if not user_db: raise HttpException(problem_status=404) return PublicUser.from_db(**user_db) -
签发 Token 的端点
用户登陆后返回jwtoken
python@Route("/token").post( plugins=[jwt_auth_plugin.encode_plugin(expires_in_s=3600)] # 设置 1 小时过期 ) async def login_get_token( credentials: OAuthLoginForm, repo: UserRepo ) -> UserProfile: user_db = await repo.find_user(credentials.username) if not user_db: raise HttpException(problem_status=404) if not verify_password(credentials.password, user_db.password_hash): raise HttpException(problem_status=401) return UserProfile(user_id=user_db.id, role=user_db.role)
为什么选择 JWTAuthPlugin
- 开箱即用:只需初始化插件并指定密钥与算法,即可在任意路由上启用 JWT 签发与解析。
- 自动注入 :解析后的
UserProfile直接以参数形式传入函数,无需手动提取和验证。 - 兼容标准 :与 OAuth2 密码模式 (
OAuth2PasswordFlow) 无缝集成,自动生成 OpenAPI 文档中/token端点的安全定义。 - 高度可定制 :你可以通过继承或组合插件,添加额外的 JWT 声明(如
exp、iat、自定义权限等)。
有了 JWTAuthPlugin,你只需关注业务逻辑,Lihil 会帮你处理繁琐的 Token 签发与校验。``````
端口限流(Rate Limiting)
Lihil 内置了一个专业且易用 的限流插件 PremierPlugin,可广泛应用于单体服务 和分布式部署中。该插件支持多种限流算法,包括:
- 固定窗口(Fixed Window)
- 滑动窗口(Sliding Window)
- 令牌桶(Token Bucket)
- 漏桶(Leaky Bucket)
这让你可以根据业务场景灵活选择限流策略,防止恶意请求、控制资源访问频率,提升服务稳定性。
示例:使用固定窗口限流
以下示例展示如何限制某个端口每秒只能访问一次:
python
from lihil import Lihil, Route
from lihil.config import lhl_get_config
from lihil.plugins.premier import PremierPlugin, throttler
from premier import AsyncRedisHandler
from redis.asyncio.client import Redis
route = Route()
premier = PremierPlugin(throttler)
@route.get(plugins=[premier.fix_window(quota=1, duration=1)]) # 每秒最多访问一次
async def hello():
return "hello"
支持分布式限流(使用 Redis)
在分布式部署中,你可以将 PremierPlugin 配置为使用 Redis 实现跨实例的限流:
python
async def lifespan():
config = lhl_get_config()
handler = AsyncRedisHandler(Redis(config.redis.URL))
throttler.config(aiohandler=handler) # 绑定异步 Redis 存储器
并在应用初始化中传入:
python
lhl = Lihil(route, lifespan=lifespan)
小贴士
- 你可以对不同端口,甚至不同用户使用不同策略,例如
premier.token_bucket(...)或premier.sliding_window(...)来切换限流算法。 - 所有策略均支持异步处理,并可根据 Redis 键动态控制作用范围(如按用户、IP、接口路径等维度限流)。
- 插件与框架高度解耦,你也可以在自定义插件中集成
throttler。
通过 PremierPlugin,Lihil 提供了强大而灵活的限流能力,帮助你轻松应对突发流量,保障服务质量。
进程内与远程消息分发
Lihil 对事件驱动架构有深度支持,内置了一个基于类型的消息分发系统,使得事件的发布与订阅变得简单且高效。无论是在单进程内还是跨进程环境,都能轻松实现松耦合的异步事件处理。
示例:基于事件的消息分发
python
from lihil import Route, status, Empty
from lihil.plugins.bus import Event, PEventBus
from lihil.plugins.testclient import LocalClient
class TodoCreated(Event):
name: str
content: str
async def listen_create(created: TodoCreated, ctx):
assert created.name
assert created.content
async def listen_twice(created: TodoCreated, ctx):
assert created.name
assert created.content
registry = MessageRegistry(event_base=Event)
registry.register(listen_create, listen_twice)
bus_plugin = BusPlugin(BusTerminal(registry))
bus_route = Route("/bus", plugins=[bus_plugin])
@bus_route.post
async def create_todo(name: str, content: str, bus: PEventBus) -> Annotated[Empty, status.OK]:
await bus.publish(TodoCreated(name, content))
在这个例子中:
- 我们定义了一个事件类
TodoCreated,包含任务名称和内容。 - 注册了两个监听函数
listen_create和listen_twice,分别响应TodoCreated事件。 - 通过
PEventBus事件总线,在/bus路由下发布事件,系统会自动调用注册的监听函数处理该事件。
这种基于类型的消息分发系统,让你的业务逻辑模块可以通过事件解耦,方便扩展和维护。
更多详情请见Lihil Anywise插件。
安装
bash
pip install lihil
总结
Lihil 致力于成为一个高性能、易用且功能丰富的 Python Web 框架,兼具 FastAPI 的简洁优雅和 Django 的开箱即用。它不仅在性能上领先,且通过强大的依赖注入系统、丰富的企业级插件、自动化的 OpenAPI 文档生成和健壮的事件驱动架构,帮助开发者极大减少重复工作,专注于业务逻辑的实现。
无论是初创项目快速上线,还是大型分布式系统的复杂需求,Lihil 都能提供灵活且高效的解决方案。通过丰富的示例和插件支持,Lihil 打破了传统框架的限制,让 Python 后端开发进入一个更高效、更智能的新时代。
欢迎PR, issues, discussion. 让我们一起改变世界吧。