【Python】使用uvicorn库:运行ASGI支持的Web应用程序实战指南
uvicorn 是一个高性能的 ASGI(Asynchronous Server Gateway Interface)服务器实现,用于运行 Python 异步 Web 应用程序。它基于 asyncio 和 uvloop(可选),以其速度快、轻量和对异步框架(如 FastAPI、Starlette)的优秀支持而闻名。uvicorn 是 FastAPI 应用的首选服务器,常用于生产环境和开发调试。
以下是对 uvicorn 库的详细介绍,包括其功能、用法和实际应用。
1. uvicorn 库的作用
uvloop(高性能事件循环)和 httptools,提供低延迟和高并发。asyncio,适合现代异步框架。2. 安装与环境要求
asgiref:ASGI 规范实现。h11:HTTP/1.1 协议实现。uvloop(高性能事件循环)、httptools(HTTP 解析)、websockets(WebSocket 支持)。pip install uvicorn
uvloop、httptools、websockets):
pip install "uvicorn[standard]"
import uvicorn
print(uvicorn.__version__) # 示例输出: 0.32.0
系统依赖(可选):
uvloop 需 C 编译器(如 gcc):
# Ubuntu
sudo apt-get install build-essential python3-dev
# MacOS
xcode-select --install
3. 核心功能与用法
uvicorn 提供命令行接口(CLI)和编程接口,支持开发和生产环境。以下是主要功能和示例。
3.1 命令行运行
通过 CLI 启动 ASGI 应用。
# 运行 FastAPI 应用
uvicorn main:app --host 0.0.0.0 --port 8000
示例(FastAPI 应用):
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello, World!"}
运行:
uvicorn main:app
输出示例:
INFO: Started server process [12345]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
访问:打开 http://127.0.0.1:8000,返回 {"message": "Hello, World!"}。
常用 CLI 参数:
--host:绑定主机(如 0.0.0.0 允许外部访问)。--port:端口号(默认 8000)。--reload:开发模式,代码更改后自动重启:
uvicorn main:app --reload
--workers:多进程工作进程数(生产环境):
uvicorn main:app --workers 4
--env-file:加载环境变量文件:
uvicorn main:app --env-file .env
--ssl-keyfile/--ssl-certfile:启用 HTTPS:
uvicorn main:app --ssl-keyfile key.pem --ssl-certfile cert.pem
3.2 编程接口
通过 Python 代码运行 uvicorn。
import uvicorn
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello, World!"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
说明:
uvicorn.run():以编程方式启动服务器。reload=True、workers=4)。3.3 热重载(开发模式)
启用 --reload 自动重启。
# main.py
import uvicorn
if __name__ == "__main__":
uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True)
说明:
main.py 后,uvicorn 自动重启应用。3.4 多进程(生产环境)
使用多工作进程提高并发。
uvicorn main:app --workers 4 --host 0.0.0.0 --port 8000
编程方式:
uvicorn.run(app, host="0.0.0.0", port=8000, workers=4)
说明:
workers:工作进程数,通常设为 CPU 核心数的 2-4 倍。gunicorn 或确保系统支持 fork。3.5 WebSocket 支持
运行支持 WebSocket 的应用。
from fastapi import FastAPI, WebSocket
from uvicorn import Config, Server
app = FastAPI()
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
await websocket.send_text("Hello, WebSocket!")
await websocket.close()
if __name__ == "__main__":
config = Config(app=app, host="0.0.0.0", port=8000, ws="websockets")
server = Server(config)
server.run()
说明:
ws="websockets":启用 WebSocket 支持,需安装 websockets。3.6 日志配置
自定义日志级别和格式。
uvicorn main:app --log-level debug
编程方式:
import uvicorn
from fastapi import FastAPI
app = FastAPI()
uvicorn.run(
app,
host="0.0.0.0",
port=8000,
log_level="debug",
log_config={
"version": 1,
"formatters": {
"default": {
"format": "%(asctime)s - %(levelname)s - %(message)s"
}
}
}
)
说明:
log_level:支持 critical、error、warning、info、debug。log_config:自定义日志格式,兼容 Python logging 配置。3.7 与 Gunicorn 集成
在生产环境中使用 gunicorn 管理 uvicorn 工作进程。
pip install gunicorn
gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app
说明:
gunicorn 提供进程管理和负载均衡。UvicornWorker 确保 ASGI 兼容性。4. 性能与特点
uvloop 和 httptools,性能接近 Node.js 和 Go。asyncio,支持高并发。--reload 模式不适合生产环境。websockets 库。5. 实际应用场景
--reload 快速迭代。gunicorn 或 Nginx 配合,提供高可用服务。示例(FastAPI + WebSocket):
from fastapi import FastAPI, WebSocket
from loguru import logger
import uvicorn
app = FastAPI()
@app.get("/health")
async def health():
logger.info("Health check requested")
return {"status": "ok"}
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
try:
while True:
data = await websocket.receive_text()
logger.info(f"Received: {data}")
await websocket.send_text(f"Echo: {data}")
except Exception as e:
logger.error(f"WebSocket error: {e}")
finally:
await websocket.close()
if __name__ == "__main__":
logger.add("app.log", rotation="1 MB", level="INFO")
uvicorn.run(
app,
host="0.0.0.0",
port=8000,
log_level="info",
ws="websockets",
reload=True
)
运行:
uvicorn main:app --reload
说明:
/health REST 端点和 /ws WebSocket 端点。loguru 记录请求和错误。--reload 支持开发模式。6. 部署与扩展
uvicorn main:app --reload --host 127.0.0.1 --port 8000
uvicorn main:app --workers 4 --host 0.0.0.0 --port 8000
gunicorn:
gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app
uvicorn main:app --ssl-keyfile key.pem --ssl-certfile cert.pem
FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
7. 注意事项
uvloop 和 httptools:
pip install uvloop httptools
workers 数:2 * CPU 核心数 + 1。limit-concurrency 限制最大连接数:
uvicorn main:app --limit-concurrency 1000
--reload 和 log_level="debug"。gunicorn 或 supervisord 管理进程。websockets:
pip install websockets
stderr)。loguru 或 logging 自定义日志。uvicorn 0.32.0 支持 Python 3.8+,与 FastAPI 0.115+ 兼容。asgiref>=3.4)。8. 综合示例
以下是一个综合示例,结合 uvicorn、FastAPI、loguru 和 httpx,展示 REST 和 WebSocket 功能:
from fastapi import FastAPI, WebSocket, Depends
from loguru import logger
import uvicorn
import httpx
from typing_extensions import Literal
from pydantic import BaseModel
# 配置日志
logger.add("app.log", rotation="1 MB", level="INFO")
app = FastAPI()
class HealthResponse(BaseModel):
status: Literal["ok", "error"]
async def get_client():
return httpx.AsyncClient()
@app.get("/health", response_model=HealthResponse)
async def health():
logger.info("Health check")
return {"status": "ok"}
@app.get("/fetch")
async def fetch_external(client: httpx.AsyncClient = Depends(get_client)):
try:
response = await client.get("https://api.github.com/repos/encode/uvicorn")
logger.info("Fetched external data")
return response.json()
except httpx.HTTPStatusError as e:
logger.error(f"HTTP error: {e}")
raise HTTPException(status_code=500, detail=str(e))
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
try:
while True:
data = await websocket.receive_text()
logger.info(f"WebSocket received: {data}")
await websocket.send_text(f"Echo: {data}")
except Exception as e:
logger.error(f"WebSocket error: {e}")
await websocket.close()
if __name__ == "__main__":
uvicorn.run(
app,
host="0.0.0.0",
port=8000,
log_level="info",
ws="websockets",
reload=True,
env_file=".env"
)
运行:
uvicorn main:app --reload
功能:
/health:返回健康状态。/fetch:调用外部 API(GitHub)。/ws:WebSocket 回显服务。loguru 记录日志,typing_extensions 增强类型注解。日志示例(app.log):
2025-05-09T12:34:56.123 | INFO | Health check
2025-05-09T12:34:56.124 | INFO | Fetched external data
2025-05-09T12:34:56.125 | INFO | WebSocket received: hello
9. 资源与文档
uvicorn 标签):https://stackoverflow.com/questions/tagged/uvicorn作者:彬彬侠