uvicorn 极简教程:Python 的 ASGI Web 服务器
介绍 Python ASGI 服务器 Uvicorn 的安装、配置及生产部署方案,并详解高性能异步库 uvloop 的原理与使用。涵盖 FastAPI 集成、命令行参数、Gunicorn 多进程管理及 uvloop 底层机制(libuv、Cython)。适合希望提升 Python 异步服务性能的开发人员参考。

介绍 Python ASGI 服务器 Uvicorn 的安装、配置及生产部署方案,并详解高性能异步库 uvloop 的原理与使用。涵盖 FastAPI 集成、命令行参数、Gunicorn 多进程管理及 uvloop 底层机制(libuv、Cython)。适合希望提升 Python 异步服务性能的开发人员参考。

Uvicorn 是一个基于 uvloop 和 httptools 构建的超快 ASGI 服务器,通常用于运行 FastAPI 或 Starlette 应用。官方文档:https://uvicorn.dev/
建议安装标准版(包含 Cython 依赖,速度更快):
pip install "uvicorn[standard]"
最小安装仅包含基础依赖:
pip install uvicorn
创建一个名为 main.py 的文件。
场景 A:配合 FastAPI(最常用)
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
场景 B:原生 ASGI 应用(不依赖框架)
async def app(scope, receive, send):
assert scope['type'] == 'http'
await send({'type': 'http.response.start', 'status': 200, 'headers': [[b'content-type', b'text/plain']],})
await send({'type': 'http.response.body', 'body': b'Hello, Uvicorn!',})
在终端中运行:
uvicorn main:app --reload
main: 你的 Python 文件名(main.py)。app: 文件中实例化的对象名(比如 app = FastAPI())。--reload: 开发模式神器。代码修改后自动重启服务器。| 参数 | 说明 | 示例 |
|---|---|---|
--reload | 开发模式,代码变动自动重启 | uvicorn main:app --reload |
--host | 绑定 IP。0.0.0.0 允许外网访问 | uvicorn main:app --host 0.0.0.0 |
--port | 指定端口(默认 8000) | uvicorn main:app --port 8080 |
--workers | 启动的工作进程数(生产环境用) | uvicorn main:app --workers 4 |
如果你想直接运行 Python 文件来启动服务器(方便调试):
# main.py 文件底部
import uvicorn
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return "OK"
if __name__ == "__main__":
# 等同于命令行:uvicorn main:app --reload
uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True)
运行方法:python main.py
在生产环境中(Linux),通常不直接裸跑 Uvicorn,而是使用 Gunicorn 作为进程管理器来管理 Uvicorn 的 Worker,以获得更好的稳定性和性能。
安装:
pip install gunicorn
运行命令:
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker
-w 4: 开启 4 个 Worker 进程。-k ...: 指定使用 Uvicorn 的 Worker 类。这是一个关于 uvloop 的极简教程。uvloop 是 Python 标准库 asyncio 的高性能替代品。
一句话介绍: 它是 Python 标准库 asyncio 的高性能替代品。
libuv(Node.js 也在用这个库)构建。pip install uvloop
使用非常简单,只需要添加两行代码:引入库,然后调用 install()。
import asyncio
import uvloop
async def main():
print("Hello, uvloop!")
await asyncio.sleep(1)
print("Done.")
if __name__ == "__main__":
# 安装 uvloop 策略
# 这行代码会将 asyncio 的默认事件循环替换为 uvloop
uvloop.install()
asyncio.run(main())
从 uvloop 0.18 开始,官方 README 推荐直接用 uvloop.run() 作为入口(它会把 asyncio.run() 配置成使用 uvloop)。
import asyncio
import uvloop
async def main():
await asyncio.sleep(0.1)
print("hello from uvloop")
uvloop.run(main())
如果你是做 Web 开发(FastAPI, Sanic, Django 等),通常不需要手动写代码。
uvloop,无需额外操作。uvloop。只要你安装了它,Uvicorn 就会自动启用。# 只要安装了 uvloop,启动时不需要额外配置
pip install uvloop
uvicorn main:app
如果想强制使用或禁用: uvicorn main:app --loop uvloop 或 --loop asyncio。
uvloop 不支持 Windows。如果在 Windows 上开发,请使用标准 asyncio,部署到 Linux 服务器时再安装 uvloop。asyncio 100% 兼容,但在极少数使用底层 API 的库中可能会有问题(非常罕见)。uvloop.install() 可能会报错或无效。技巧: 可以用 try...except 兼容:
try:
import uvloop
uvloop.install()
except ImportError:
pass # Windows 下没有 uvloop,回退到标准 asyncio
uvloop 之所以快,并不是因为它使用了什么魔法,而是因为它通过 Cython 将 Python 标准库 asyncio 的核心逻辑(事件循环)用 C 语言 重新写了一遍,底层则由高性能的 libuv 驱动。
可以将它的原理拆解为三个核心支柱:核心引擎 (libuv)、桥梁技术 (Cython) 和 极度优化的内存管理。
uvloop 的名字就来源于 libuv。
epoll,在 macOS 上使用 kqueue,这些是操作系统能够提供的最高效的 I/O 通知机制。这是 uvloop 最关键的实现细节。uvloop 不是简单地用 Python 调 C 库,而是用 Cython 编写的。
uvloop 并不是'修补'了 asyncio,而是实现了 asyncio.AbstractEventLoop 接口的一个全新类。async def)时,它才会切换回 Python。仅仅用 C 重写并不足以达到现在的速度,uvloop 的作者(MagicStack 团队)在实现细节上做了大量优化:
在异步编程中,会频繁创建小的对象(比如 Future 对象、Task 对象、Handle 对象)。
Python 的函数调用是有开销的(参数解包、栈帧创建等)。
uvloop 在内部处理 libuv 的回调时,尽可能保持在 C 层面流转,只有在最后一步才将数据转化为 Python 对象传给用户代码。uvloop 针对不同类型的 I/O(TCP, UDP, Pipe, Signal)进行了专门的优化路径,而不是使用通用的低效封装。
为了直观理解,我们可以对比一下调用路径:
原生 asyncio 的路径:
Python 代码 -> asyncio (Python 循环) -> Select/Epoll (C 模块) -> 操作系统
uvloop 的路径:
Python 代码 -> uvloop (C/Cython 循环) -> libuv (C 库) -> 操作系统
如果你准备进一步刨源码,按这个顺序最容易建立整体感:
loop.pyx:loop 的初始化、call_soon_threadsafe 唤醒、signals self-pipe、reader/writer 注册等。handles/async_.pyx:uv_async_t 封装,理解'跨线程唤醒'的 C 层路径。cbhandles.pyx:TimerHandle 如何用 UVTimer(libuv timer)实现。dns.pyx:DNS request 如何对接 libuv。poll/udp/tcp/stream 等:transport/protocol 如何把 socket I/O 对接到 libuv 的 handle。
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online