1. Uvicorn 是什么?它解决什么问题? #
Uvicorn 是一个轻量级、超快速的 ASGI(异步服务器网关接口)服务器。它是运行 FastAPI、Starlette 等异步 Web 应用的服务器程序。
1.1 为什么需要 Uvicorn? #
简单理解:
- FastAPI/Starlette:Web 框架,定义了如何处理请求和返回响应
- Uvicorn:服务器,负责接收 HTTP 请求、调用框架、返回响应
类比:
- 框架 = 餐厅的菜单和厨师(定义做什么菜)
- 服务器 = 餐厅的服务员(负责接待客人、传递订单)
1.2 Uvicorn 的核心特点 #
- 极高性能:基于
uvloop(高性能事件循环)和httptools(C 语言 HTTP 解析器) - ASGI 兼容:完全支持异步 Web 应用
- 轻量级:代码简洁,依赖少
- 易于使用:简单的命令行接口和 Python API
2. 前置知识 #
在学习 Uvicorn 之前,你需要了解以下基础知识。
2.1 什么是服务器? #
服务器(Server) 是运行在计算机上的程序,它:
- 监听网络端口(如 8000)
- 接收客户端(如浏览器)的请求
- 处理请求并返回响应
简单理解:服务器就像一个餐厅,等待客人(客户端)来点餐(发送请求),然后提供食物(返回响应)。
2.2 什么是 ASGI? #
ASGI(Asynchronous Server Gateway Interface,异步服务器网关接口) 是 Python Web 应用和服务器之间的标准接口。
ASGI vs WSGI:
- WSGI(旧标准):同步接口,一次只能处理一个请求
- ASGI(新标准):异步接口,可以同时处理多个请求
为什么需要 ASGI:
- 支持异步编程(
async/await) - 支持 WebSocket
- 性能更好
2.3 异步编程基础 #
Uvicorn 是异步服务器,你需要了解:
- async def:定义异步函数
- await:等待异步操作完成
- asyncio:Python 的异步编程库
如果你不熟悉异步编程,建议先学习 Python 的 asyncio 模块。
2.4 Python 基础知识 #
你需要熟悉:
- 模块导入:
import语句 - 函数调用:如何调用函数
- 命令行:基本的命令行操作
3. 安装与环境准备 #
3.1 安装 Uvicorn #
使用 pip 安装:
# 标准版(推荐)
pip install uvicorn[standard]
# 或者基础版
pip install uvicorn说明:
uvicorn[standard]:包含所有推荐依赖(uvloop、httptools 等),性能更好uvicorn:基础版本,功能完整但性能稍差
3.2 验证安装 #
创建一个简单的测试应用 test_app.py:
# 导入必要的模块
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
# 定义处理函数
async def homepage(request):
# 返回 JSON 响应
return JSONResponse({"message": "Uvicorn 安装成功!"})
# 创建应用
app = Starlette(
routes=[
Route("/", homepage),
]
)
# 运行应用(使用 uvicorn)
if __name__ == "__main__":
import uvicorn
# 运行服务器,监听 8000 端口
uvicorn.run(app, host="0.0.0.0", port=8000)运行测试:
python test_app.py然后在浏览器访问 http://localhost:8000,应该能看到 {"message": "Uvicorn 安装成功!"}。
4. 基本使用:命令行方式 #
Uvicorn 最简单的使用方式是通过命令行运行。
4.1 创建示例应用 #
首先,创建一个简单的应用 main.py:
# 导入必要的模块
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
# 定义处理函数
async def read_root(request):
# 返回 JSON 响应
return JSONResponse({"message": "Hello Uvicorn!"})
# 创建应用实例
# 变量名必须是 app(命令行默认查找这个变量)
app = Starlette(
routes=[
Route("/", read_root),
]
)4.2 运行应用 #
在命令行中运行:
# 基本运行(默认监听 127.0.0.1:8000)
uvicorn main:app
# 指定主机和端口
uvicorn main:app --host 0.0.0.0 --port 8000
# 启用热重载(开发模式,代码修改后自动重启)
uvicorn main:app --reload
# 设置日志级别
uvicorn main:app --log-level debug命令说明:
main:app:main是文件名(不含.py),app是应用实例的变量名--host 0.0.0.0:监听所有网络接口(允许外部访问)--port 8000:使用 8000 端口--reload:开发模式,代码修改后自动重启服务器--log-level debug:设置日志级别为 debug(显示详细信息)
5. 基本使用:Python 代码方式 #
除了命令行,你也可以在 Python 代码中直接运行 Uvicorn。
5.1 使用 uvicorn.run() 函数 #
# 导入必要的模块
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
import uvicorn
# 定义处理函数
async def read_root(request):
# 返回 JSON 响应
return JSONResponse({"message": "Hello from Python!"})
# 创建应用实例
app = Starlette(
routes=[
Route("/", read_root),
]
)
# 在 Python 代码中运行服务器
# uvicorn.run() 函数用于启动服务器
if __name__ == "__main__":
# 方式 1:传入应用实例
uvicorn.run(
app, # 应用实例
host="0.0.0.0", # 主机地址
port=8000, # 端口号
reload=True # 是否启用热重载(开发模式)
)5.2 使用字符串指定应用 #
# 导入必要的模块
import uvicorn
# 使用字符串指定应用位置
# "main:app" 表示 main.py 文件中的 app 变量
if __name__ == "__main__":
uvicorn.run(
"main:app", # 应用位置(字符串格式)
host="0.0.0.0", # 主机地址
port=8000, # 端口号
reload=True, # 启用热重载
log_level="info" # 日志级别
)两种方式的区别:
- 传入应用实例:直接传入应用对象,更直观
- 传入字符串:Uvicorn 会自动导入,适合应用在其他文件中定义
6. 常用配置选项 #
Uvicorn 提供了丰富的配置选项,让我们学习最常用的几个。
6.1 基本配置 #
# 导入必要的模块
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
import uvicorn
# 定义处理函数
async def read_root(request):
return JSONResponse({"message": "Hello Uvicorn!"})
# 创建应用
app = Starlette(
routes=[
Route("/", read_root),
]
)
# 运行应用,配置常用选项
if __name__ == "__main__":
uvicorn.run(
app,
host="0.0.0.0", # 主机地址(0.0.0.0 表示监听所有网络接口)
port=8000, # 端口号
reload=True, # 是否启用热重载(开发时使用)
log_level="info", # 日志级别:critical, error, warning, info, debug, trace
access_log=True, # 是否记录访问日志
workers=1 # 工作进程数(开发时通常为 1,生产环境可以增加)
)6.2 开发环境配置 #
# 导入必要的模块
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
import uvicorn
# 定义处理函数
async def read_root(request):
return JSONResponse({"message": "开发模式"})
# 创建应用
app = Starlette(
routes=[
Route("/", read_root),
]
)
# 开发环境配置
if __name__ == "__main__":
uvicorn.run(
app,
host="127.0.0.1", # 只监听本地(更安全)
port=8000,
reload=True, # 启用热重载
reload_dirs=["./"], # 监听哪些目录的变化
log_level="debug", # 详细的日志(便于调试)
access_log=True # 记录访问日志
)6.3 生产环境配置(简化版) #
# 导入必要的模块
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
import uvicorn
# 定义处理函数
async def read_root(request):
return JSONResponse({"message": "生产模式"})
# 创建应用
app = Starlette(
routes=[
Route("/", read_root),
]
)
# 生产环境配置(简化版)
if __name__ == "__main__":
uvicorn.run(
app,
host="0.0.0.0", # 监听所有网络接口
port=8000,
reload=False, # 禁用热重载(生产环境不需要)
log_level="warning", # 只记录警告和错误
access_log=True, # 记录访问日志
workers=4 # 使用多个工作进程(根据 CPU 核心数调整)
)配置说明:
- host:服务器监听的主机地址
127.0.0.1:只允许本地访问0.0.0.0:允许所有网络接口访问
- port:服务器监听的端口号
- reload:是否启用热重载(开发时使用,生产环境禁用)
- log_level:日志级别,从低到高:critical < error < warning < info < debug < trace
- access_log:是否记录访问日志
- workers:工作进程数(多进程模式,提高并发能力)
7. 运行 FastAPI 应用 #
Uvicorn 最常用的场景是运行 FastAPI 应用。
7.1 创建 FastAPI 应用 #
# 导入 FastAPI
from fastapi import FastAPI
# 创建 FastAPI 应用实例
app = FastAPI()
# 定义路由
@app.get("/")
async def read_root():
# 返回 JSON 响应
return {"message": "Hello FastAPI with Uvicorn!"}
# 运行应用
if __name__ == "__main__":
import uvicorn
# 运行 FastAPI 应用
uvicorn.run(app, host="0.0.0.0", port=8000, reload=True)7.2 使用命令行运行 #
# 运行 FastAPI 应用
uvicorn main:app --reload
# 访问 http://localhost:8000 查看应用
# 访问 http://localhost:8000/docs 查看自动生成的 API 文档8. 运行 Starlette 应用 #
Uvicorn 也可以运行 Starlette 应用。
8.1 创建 Starlette 应用 #
# 导入必要的模块
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
# 定义处理函数
async def read_root(request):
# 返回 JSON 响应
return JSONResponse({"message": "Hello Starlette with Uvicorn!"})
# 创建 Starlette 应用实例
app = Starlette(
routes=[
Route("/", read_root),
]
)
# 运行应用
if __name__ == "__main__":
import uvicorn
# 运行 Starlette 应用
uvicorn.run(app, host="0.0.0.0", port=8000, reload=True)8.2 使用命令行运行 #
# 运行 Starlette 应用
uvicorn main:app --reload
# 访问 http://localhost:8000 查看应用9. 热重载:开发时的便利功能 #
热重载(Hot Reload) 是开发时的便利功能:当你修改代码后,服务器会自动重启,无需手动停止和启动。
9.1 启用热重载 #
# 导入必要的模块
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
import uvicorn
# 定义处理函数
async def read_root(request):
# 修改这里的返回值,保存文件后服务器会自动重启
return JSONResponse({"message": "修改我,然后保存文件!"})
# 创建应用
app = Starlette(
routes=[
Route("/", read_root),
]
)
# 启用热重载
if __name__ == "__main__":
uvicorn.run(
app,
host="0.0.0.0",
port=8000,
reload=True, # 启用热重载
reload_dirs=["./"] # 监听当前目录的变化
)使用方法:
- 运行程序
- 修改代码(如修改返回的消息)
- 保存文件
- 服务器会自动检测变化并重启
- 刷新浏览器即可看到新内容
注意:热重载只在开发时使用,生产环境应该禁用(reload=False)。
10. 日志配置:查看服务器运行信息 #
Uvicorn 提供了详细的日志功能,帮助你了解服务器的运行状态。
10.1 日志级别 #
# 导入必要的模块
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
import uvicorn
# 定义处理函数
async def read_root(request):
return JSONResponse({"message": "查看日志输出"})
# 创建应用
app = Starlette(
routes=[
Route("/", read_root),
]
)
# 配置不同的日志级别
if __name__ == "__main__":
uvicorn.run(
app,
host="0.0.0.0",
port=8000,
log_level="debug", # 日志级别:critical, error, warning, info, debug, trace
access_log=True # 是否记录访问日志
)日志级别说明:
- critical:只显示严重错误
- error:显示错误信息
- warning:显示警告信息
- info:显示一般信息(默认)
- debug:显示调试信息(最详细)
- trace:显示跟踪信息(最最详细)
10.2 查看日志输出 #
运行服务器后,你会看到类似以下的日志输出:
INFO: Started server process [12345]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO: 127.0.0.1:54321 - "GET / HTTP/1.1" 200 OK日志说明:
- 第一行:服务器进程已启动
- 第二行:等待应用启动
- 第三行:应用启动完成
- 第四行:服务器运行地址
- 第五行:访问日志(客户端 IP、请求方法、路径、状态码)
11. 多进程模式:提高并发能力 #
默认情况下,Uvicorn 使用单进程模式。对于生产环境,可以使用多进程模式提高并发能力。
11.1 单进程模式(开发环境) #
# 导入必要的模块
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
import uvicorn
# 定义处理函数
async def read_root(request):
return JSONResponse({"message": "单进程模式"})
# 创建应用
app = Starlette(
routes=[
Route("/", read_root),
]
)
# 单进程模式(默认)
if __name__ == "__main__":
uvicorn.run(
app,
host="0.0.0.0",
port=8000,
workers=1 # 单进程(开发环境)
)11.2 多进程模式(生产环境) #
# 导入必要的模块
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
import uvicorn
import multiprocessing
# 定义处理函数
async def read_root(request):
return JSONResponse({"message": "多进程模式"})
# 创建应用
app = Starlette(
routes=[
Route("/", read_root),
]
)
# 多进程模式
if __name__ == "__main__":
# 获取 CPU 核心数
cpu_count = multiprocessing.cpu_count()
# 工作进程数通常是 CPU 核心数的 2 倍 + 1
workers = cpu_count * 2 + 1
uvicorn.run(
app,
host="0.0.0.0",
port=8000,
workers=workers, # 多进程(生产环境)
reload=False # 生产环境禁用热重载
)说明:
- 单进程模式:适合开发环境,简单易用
- 多进程模式:适合生产环境,提高并发处理能力
- workers 数量:通常设置为 CPU 核心数的 2 倍 + 1
12. 常见错误与最佳实践 #
12.1 常见错误 #
错误 1:找不到应用 #
# 错误:应用变量名不匹配
# main.py 中定义的是 my_app,但命令行使用的是 app
uvicorn main:app # 错误:找不到 app 变量
# 正确:使用正确的变量名
uvicorn main:my_app # 正确错误 2:端口已被占用 #
# 错误:端口 8000 已被其他程序占用
uvicorn.run(app, port=8000) # 可能报错:Address already in use
# 正确:使用其他端口
uvicorn.run(app, port=8001) # 使用 8001 端口错误 3:忘记启用热重载 #
# 开发时忘记启用热重载,每次修改代码都要手动重启
uvicorn.run(app, reload=False) # 不方便
# 正确:开发时启用热重载
uvicorn.run(app, reload=True) # 方便12.2 最佳实践 #
开发环境:
- 使用
reload=True启用热重载 - 使用
log_level="debug"查看详细信息 - 使用
workers=1单进程模式
- 使用
生产环境:
- 使用
reload=False禁用热重载 - 使用
log_level="warning"只记录警告和错误 - 使用
workers=4或更多(根据 CPU 核心数)
- 使用
端口选择:
- 开发环境:使用 8000、8001 等常用端口
- 生产环境:使用标准端口(80、443)或配置反向代理
13. Uvicorn 与其他组件的关系 #
13.1 Uvicorn 在 Web 开发中的位置 #
客户端(浏览器)
↓
Uvicorn(服务器)
↓
FastAPI/Starlette(框架)
↓
你的应用代码简单理解:
- 客户端:发送请求(如浏览器)
- Uvicorn:接收请求,调用框架
- 框架:处理请求,执行你的代码
- 你的代码:处理业务逻辑,返回响应
13.2 为什么选择 Uvicorn? #
- 性能优秀:基于 uvloop 和 httptools,性能极佳
- 简单易用:配置简单,API 清晰
- 生态良好:与 FastAPI、Starlette 完美集成
- 功能完整:支持异步、WebSocket 等特性
14. 总结 #
14.1 核心概念回顾 #
- Uvicorn:ASGI 服务器,用于运行异步 Web 应用
- ASGI:异步服务器网关接口
- 热重载:开发时自动重启服务器
- 多进程模式:提高并发处理能力
- 日志级别:控制日志输出的详细程度
14.2 基本使用流程 #
- 安装 Uvicorn:
pip install uvicorn[standard] - 创建应用(FastAPI 或 Starlette)
- 运行应用:
- 命令行:
uvicorn main:app --reload - Python 代码:
uvicorn.run(app, host="0.0.0.0", port=8000)
- 命令行: