文章目录
- 一、基础知识学习(入门)
-
- [Sanic 简介](#Sanic 简介)
- [什么是 Sanic 框架?](#什么是 Sanic 框架?)
- [Sanic 的优势和适用场景](#Sanic 的优势和适用场景)
-
- [1. 高性能](#1. 高性能)
- [2. 异步支持](#2. 异步支持)
- [3. 简洁易用](#3. 简洁易用)
- [4. WebSocket 支持](#4. WebSocket 支持)
- [5. 灵活扩展](#5. 灵活扩展)
- 环境搭建
-
- [1. 安装 Python(3.7 及以上版本)](#1. 安装 Python(3.7 及以上版本))
- [2. 创建虚拟环境](#2. 创建虚拟环境)
- [3. 安装 Sanic](#3. 安装 Sanic)
- [第一个 Sanic 应用](#第一个 Sanic 应用)
-
- [1. 创建应用文件](#1. 创建应用文件)
- [2. 理解 app.run() 的参数配置](#2. 理解 app.run() 的参数配置)
- [3. 启动应用](#3. 启动应用)
- [4. 访问应用](#4. 访问应用)
- [二、核心概念与 API 学习](#二、核心概念与 API 学习)
-
- 路由
-
- 路由的定义和动态参数处理
- [路由匹配规则和方法(`GET`、`POST`、`PUT`、`DELETE` 等)](#路由匹配规则和方法(
GET
、POST
、PUT
、DELETE
等))
- 请求与响应
-
- [`request` 对象的属性(`args`、`form`、`json`、`headers` 等)](#
request
对象的属性(args
、form
、json
、headers
等)) - [`response` 对象的生成方法(`json()`、`text()`、`html()` 等)](#
response
对象的生成方法(json()
、text()
、html()
等))
- [`request` 对象的属性(`args`、`form`、`json`、`headers` 等)](#
- 中间件
-
- [中间件的定义与应用(`request` 和 `response` 阶段)](#中间件的定义与应用(
request
和response
阶段)) - 使用中间件进行日志记录或验证请求
- [中间件的定义与应用(`request` 和 `response` 阶段)](#中间件的定义与应用(
- 异步处理
-
- [Python 异步编程基础(`async`/`await` 的使用)](#Python 异步编程基础(
async
/await
的使用)) - 异步任务的实现与调度
- [Python 异步编程基础(`async`/`await` 的使用)](#Python 异步编程基础(
- 蓝图(Blueprints)
- 异常处理
- 三、进阶功能与性能优化
-
- [WebSocket 支持](#WebSocket 支持)
-
- [实现 WebSocket 通信的简单服务](#实现 WebSocket 通信的简单服务)
- 处理实时消息与广播功能
- 文件上传与下载
- 中间件
-
- [中间件的定义与应用(`request` 和 `response` 阶段)](#中间件的定义与应用(
request
和response
阶段)) - 使用中间件进行日志记录或验证请求
- [中间件的定义与应用(`request` 和 `response` 阶段)](#中间件的定义与应用(
- 异步处理
-
- [Python 异步编程基础(`async`/`await` 的使用)](#Python 异步编程基础(
async
/await
的使用)) - 异步任务的实现与调度
- [Python 异步编程基础(`async`/`await` 的使用)](#Python 异步编程基础(
- 蓝图(Blueprints)
- 异常处理
一、基础知识学习(入门)
Sanic 简介
Sanic 是一个基于 Python 的异步 Web 框架,它使用 Python 的 asyncio
库实现高效的异步请求处理,适合高并发环境下的 Web 应用开发。Sanic 的设计理念是轻量级且高性能,特别适用于需要处理大量并发请求的应用,比如实时聊天、推送通知、API 服务等。
与传统的同步 Web 框架相比,Sanic 利用异步特性,通过 async
和 await
语法大幅提升了 Web 服务的响应能力,能够同时处理多个 I/O 密集型任务,而不会阻塞服务器的主线程。
什么是 Sanic 框架?
Sanic 是一个用 Python 编写的 Web 框架,专注于高性能和异步编程。它允许开发者通过异步的方式处理 HTTP 请求,从而提高并发性能。Sanic 完全支持 Python 3.7 及以上版本,并且支持 async/await 语法,使得编写高并发、实时通信和长连接等服务变得更加简单高效。
与其他 Web 框架(如 Flask 或 Django)相比,Sanic 的主要特点是其内置的异步支持,它可以在一个请求的生命周期内并行处理多个 I/O 操作。这使得 Sanic 在面对高并发或实时数据更新的场景时,比传统框架表现出更高的性能。
Sanic 的优势和适用场景
1. 高性能
Sanic 利用异步非阻塞 I/O 和 asyncio
协程,能够大幅提升并发请求的处理效率。相比于传统的同步框架,Sanic 能够在处理大量并发连接时,保持高效且稳定。
2. 异步支持
Sanic 本质上是异步的框架,使用 async
和 await
语法来处理请求和响应。对于网络请求、数据库操作和文件 I/O 等耗时操作,Sanic 能够高效并发执行,而不会阻塞主线程。
3. 简洁易用
Sanic 提供了简单直观的 API,开发者可以快速上手。无论是新手还是经验丰富的开发者,都能通过简洁的语法和易于理解的文档快速构建 Web 应用。
4. WebSocket 支持
Sanic 内置对 WebSocket 的支持,适合实时聊天、实时通知、推送等应用场景,能够处理持续的双向通信。
5. 灵活扩展
Sanic 提供了蓝图(Blueprint)和中间件支持,方便开发者模块化管理代码,并对请求生命周期进行控制。可以轻松集成数据库、缓存、日志等第三方服务,满足不同的业务需求。
适用场景:
- 高并发 Web API 服务
- 实时聊天应用
- 推送通知系统
- IoT(物联网)系统
- 数据流和实时分析服务
环境搭建
在开始使用 Sanic 开发应用之前,首先需要搭建开发环境。
1. 安装 Python(3.7 及以上版本)
Sanic 支持 Python 3.7 及以上版本。如果尚未安装 Python,可以访问 Python 官网 下载并安装。
在终端中检查 Python 版本:
bash
python --version
确保安装的是 Python 3.7 或更高版本。
2. 创建虚拟环境
为了避免与系统其他项目的依赖冲突,建议使用 Python 的虚拟环境管理工具(如 venv
或 virtualenv
)来为项目创建一个独立的环境。
使用 venv
创建虚拟环境的步骤:
bash
python -m venv sanic_env
激活虚拟环境:
-
在 Linux/macOS 上:
bashsource sanic_env/bin/activate
-
在 Windows 上:
bash.\sanic_env\Scripts\activate
激活虚拟环境后,可以在这个环境中安装所有依赖,不会影响系统的其他 Python 项目。
3. 安装 Sanic
安装 Sanic 框架,只需要运行以下命令:
bash
pip install sanic
安装完成后,可以在 Python 环境中通过 import sanic
测试是否安装成功。
第一个 Sanic 应用
现在,我们开始编写第一个简单的 Sanic 应用,它会在访问根路径时返回一条简单的 JSON 消息。
1. 创建应用文件
在项目目录下,创建一个新的 Python 文件,比如 app.py
,然后添加以下代码:
python
from sanic import Sanic
from sanic.response import json
# 创建一个 Sanic 实例
app = Sanic("HelloWorldApp")
# 创建路由,处理根路径请求
@app.route("/")
async def hello(request):
return json({"message": "Hello, Sanic!"})
# 运行应用
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
2. 理解 app.run() 的参数配置
app.run()
方法用于启动 Sanic 应用,它接受多个参数来配置应用的运行方式。常用参数如下:
- host :指定应用的主机地址,默认为
127.0.0.1
(即本机地址)。设置为"0.0.0.0"
可以让应用对外开放,允许其他设备访问。 - port :指定应用监听的端口号,默认为
8000
。可以根据需要修改为其他端口。 - debug :如果设置为
True
,将在开发过程中启用调试模式,方便调试和查看错误信息。默认情况下,开发模式是启用的。
3. 启动应用
在终端中,进入 app.py
所在的目录,并运行以下命令启动应用:
bash
python app.py
会看到类似如下的信息,表示应用已启动:
[2025-01-13 00:00:00 +0000] [1234] [INFO] Sanic: Sanic version 22.6.0
[2025-01-13 00:00:00 +0000] [1234] [INFO] Goin' Fast @ http://0.0.0.0:8000
4. 访问应用
打开浏览器,访问 http://127.0.0.1:8000/
,会看到返回的 JSON 响应:
json
{
"message": "Hello, Sanic!"
}
二、核心概念与 API 学习
路由
路由的定义和动态参数处理
在 Sanic 中,路由用于定义请求的 URL 路径和处理函数之间的映射关系。通过装饰器的形式,将函数与路由路径绑定,当访问指定路径时,Sanic 会调用相应的处理函数。
最基础的路由定义方式如下:
python
@app.route("/hello")
async def hello(request):
return json({"message": "Hello, Sanic!"})
此外,Sanic 支持动态路由参数,可以通过路径中的占位符定义动态参数。例如:
python
@app.route("/user/<user_id>")
async def get_user(request, user_id):
return json({"user_id": user_id})
在上面的例子中,<user_id>
是动态参数,Sanic 会提取 URL 中的值并将其传递给路由处理函数。
路由匹配规则和方法(GET
、POST
、PUT
、DELETE
等)
Sanic 支持多种 HTTP 方法(如 GET
、POST
、PUT
、DELETE
)的路由定义。默认情况下,路由会匹配 GET
请求,但可以显式地指定 HTTP 方法。
例如,定义 POST
请求路由:
python
@app.route("/login", methods=["POST"])
async def login(request):
data = request.json # 获取 JSON 数据
return json({"status": "success", "data": data})
同样,也可以定义多个方法的路由:
python
@app.route("/user/<user_id>", methods=["GET", "PUT"])
async def user_info(request, user_id):
if request.method == "GET":
return json({"user_id": user_id, "action": "get"})
elif request.method == "PUT":
return json({"user_id": user_id, "action": "update"})
Sanic 会根据请求方法自动调用相应的路由处理函数。
请求与响应
request
对象的属性(args
、form
、json
、headers
等)
Sanic 的 request
对象提供了丰富的属性来获取请求中的各种数据:
args
:获取查询参数。例如,/search?q=python
中,q
可以通过request.args.get("q")
获取。form
:获取表单数据。对于POST
请求中的表单数据,可以使用request.form
。json
:如果请求体是 JSON 格式的数据,可以使用request.json
来获取。headers
:访问请求头部信息。例如,request.headers["User-Agent"]
获取用户代理。
python
@app.route("/search", methods=["GET"])
async def search(request):
query = request.args.get("q", "")
return json({"query": query})
@app.route("/login", methods=["POST"])
async def login(request):
form_data = request.form
return json({"status": "success", "data": form_data})
response
对象的生成方法(json()
、text()
、html()
等)
Sanic 的 response
对象提供了多种方法来生成不同类型的响应:
json()
:返回 JSON 格式的响应。text()
:返回纯文本格式的响应。html()
:返回 HTML 格式的响应。
python
@app.route("/json")
async def json_response(request):
return json({"message": "This is a JSON response"})
@app.route("/text")
async def text_response(request):
return text("This is a plain text response")
@app.route("/html")
async def html_response(request):
return html("<h1>This is an HTML response</h1>")
这些方法会自动设置合适的 Content-Type
头,确保客户端能够正确解析响应数据。
中间件
中间件的定义与应用(request
和 response
阶段)
中间件是处理请求和响应的钩子函数,它们在请求到达路由之前和响应返回客户端之前执行。Sanic 支持两种类型的中间件:
- 请求中间件:在请求被路由处理前执行。
- 响应中间件:在响应返回客户端前执行。
定义中间件的方式如下:
python
from sanic import Sanic
from sanic.response import json
app = Sanic("MiddlewareExample")
# 请求中间件
@app.middleware("request")
async def add_request_id(request):
request["request_id"] = "12345"
# 响应中间件
@app.middleware("response")
async def add_custom_header(request, response):
response.headers["X-Custom-Header"] = "This is a custom header"
return response
@app.route("/")
async def index(request):
return json({"message": "Hello with Middleware!"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
使用中间件进行日志记录或验证请求
中间件非常适合用于日志记录、请求验证、身份验证等任务。例如,可以在请求阶段记录日志,或者在响应阶段修改返回的内容:
python
@app.middleware("request")
async def log_request(request):
print(f"Incoming request: {request.method} {request.path}")
异步处理
Python 异步编程基础(async
/await
的使用)
Sanic 的最大特点之一就是异步处理请求。可以在路由处理函数中使用 async
和 await
,让函数变为异步执行,从而提高并发性能。
async
:用于定义异步函数。await
:用于等待异步操作的结果。
例如,使用 async
和 await
来模拟一个耗时操作:
python
@app.route("/long_task")
async def long_task(request):
await asyncio.sleep(5) # 模拟耗时任务
return json({"message": "Task completed"})
Sanic 会在等待 asyncio.sleep(5)
时不阻塞其他请求,充分利用异步特性。
异步任务的实现与调度
在 Sanic 中,可以使用 asyncio
来调度异步任务。例如,使用后台任务执行耗时操作:
python
import asyncio
@app.route("/start_task")
async def start_task(request):
asyncio.create_task(long_running_task())
return json({"message": "Task started!"})
async def long_running_task():
await asyncio.sleep(10)
print("Task finished")
蓝图(Blueprints)
理解蓝图的概念和用途
蓝图是 Sanic 中用于组织应用代码的工具,它允许将路由和视图函数分组,以便于模块化开发。通过蓝图,可以将一个大型应用拆分成多个小的模块。
例如,创建一个蓝图并在应用中注册:
python
from sanic import Blueprint
# 创建蓝图
bp = Blueprint("user")
@bp.route("/profile")
async def profile(request):
return json({"message": "User Profile"})
# 注册蓝图
app.blueprint(bp)
如何使用蓝图进行模块化开发
通过使用蓝图,可以将不同功能的路由分别放在不同的文件中,实现模块化管理。例如,将用户相关的路由放在 user.py
文件中,产品相关的路由放在 product.py
中。
python
# user.py
from sanic import Blueprint
bp = Blueprint("user")
@bp.route("/profile")
async def profile(request):
return json({"message": "User Profile"})
# main.py
from sanic import Sanic
from user import bp
app = Sanic("ModularApp")
app.blueprint(bp)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
异常处理
捕获全局异常
Sanic 允许全局捕获异常并进行自定义处理。可以使用 @app.exception
装饰器来捕获全局异常:
python
@app.exception(Exception)
async def handle_exception(request, exception):
return json({"error": str(exception)}, status=500)
自定义异常处理方法
也可以定义特定的异常处理函数,根据不同的错误类型做不同的处理。例如,处理 404
错误时返回自定义页面:
python
@app.exception(NotFound)
async def handle_not_found(request, exception):
return html("<h1>Page Not Found</h1>", status=404)
三、进阶功能与性能优化
WebSocket 支持
实现 WebSocket 通信的简单服务
WebSocket 是一种在客户端和服务器之间建立全双工通信的协议,允许服务器和客户端之间实时双向传输数据。Sanic 提供了对 WebSocket 的原生支持,使用 @app.websocket()
装饰器可以轻松实现 WebSocket 服务。
以下是一个简单的 WebSocket 示例:
python
@app.websocket('/ws')
async def websocket_handler(request, ws):
while True:
message = await ws.recv() # 接收消息
print(f"Received message: {message}")
await ws.send(f"Echo: {message}") # 发送回显消息
在此代码中,客户端发送的消息会被服务器接收到,并通过 ws.send()
返回给客户端,实现了基本的 WebSocket 双向通信。
处理实时消息与广播功能
除了基本的回显功能,WebSocket 还可以用于实现实时消息推送或广播。例如,当一个客户端发送消息时,其他所有连接的客户端也能收到该消息:
python
sockets = [] # 存储 WebSocket 连接
@app.websocket('/ws')
async def websocket_handler(request, ws):
sockets.append(ws)
try:
while True:
message = await ws.recv()
for socket in sockets:
if socket != ws: # 不广播给发送者
await socket.send(message)
except:
sockets.remove(ws) # 断开连接时移除
在这个例子中,服务器会将每个客户端发送的消息广播给其他所有客户端,从而实现了实时通信功能。
文件上传与下载
实现文件上传接口
Sanic 提供了 request.files
来处理文件上传。可以通过 POST
请求上传文件,并将其保存到服务器本地。
python
@app.route('/upload', methods=["POST"])
async def upload_file(request):
file = request.files.get('file') # 获取上传的文件
if file:
with open(f"./uploads/{file.name}", 'wb') as f:
f.write(file.body) # 将文件内容写入磁盘
return json({"status": "success", "filename": file.name})
return json({"status": "fail", "message": "No file uploaded"})
此代码将上传的文件保存到服务器的 uploads/
文件夹,并返回上传文件的文件名。
提供文件下载服务
Sanic 通过 send_file()
方法支持文件下载。可以根据文件路径返回文件给客户端:
python
from sanic.response import send_file
@app.route('/download/<filename>', methods=["GET"])
async def download_file(request, filename):
file_path = f"./uploads/{filename}"
return await send_file(file_path)
客户端可以访问 /download/<filename>
来下载指定的文件。send_file
会自动处理文件传输,支持流式传输,适合大文件下载。
中间件
中间件的定义与应用(request
和 response
阶段)
中间件是处理请求和响应的钩子函数,它们在请求到达路由之前和响应返回客户端之前执行。Sanic 支持两种类型的中间件:
- 请求中间件:在请求被路由处理前执行。
- 响应中间件:在响应返回客户端前执行。
定义中间件的方式如下:
python
from sanic import Sanic
from sanic.response import json
app = Sanic("MiddlewareExample")
# 请求中间件
@app.middleware("request")
async def add_request_id(request):
request["request_id"] = "12345"
# 响应中间件
@app.middleware("response")
async def add_custom_header(request, response):
response.headers["X-Custom-Header"] = "This is a custom header"
return response
@app.route("/")
async def index(request):
return json({"message": "Hello with Middleware!"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
使用中间件进行日志记录或验证请求
中间件非常适合用于日志记录、请求验证、身份验证等任务。例如,可以在请求阶段记录日志,或者在响应阶段修改返回的内容:
python
@app.middleware("request")
async def log_request(request):
print(f"Incoming request: {request.method} {request.path}")
异步处理
Python 异步编程基础(async
/await
的使用)
Sanic 的最大特点之一就是异步处理请求。可以在路由处理函数中使用 async
和 await
,让函数变为异步执行,从而提高并发性能。
async
:用于定义异步函数。await
:用于等待异步操作的结果。
例如,使用 async
和 await
来模拟一个耗时操作:
python
@app.route("/long_task")
async def long_task(request):
await asyncio.sleep(5) # 模拟耗时任务
return json({"message": "Task completed"})
Sanic 会在等待 asyncio.sleep(5)
时不阻塞其他请求,充分利用异步特性。
异步任务的实现与调度
在 Sanic 中,可以使用 asyncio
来调度异步任务。例如,使用后台任务执行耗时操作:
python
import asyncio
@app.route("/start_task")
async def start_task(request):
asyncio.create_task(long_running_task())
return json({"message": "Task started!"})
async def long_running_task():
await asyncio.sleep(10)
print("Task finished")
蓝图(Blueprints)
理解蓝图的概念和用途
蓝图是 Sanic 中用于组织应用代码的工具,它允许将路由和视图函数分组,以便于模块化开发。通过蓝图,可以将一个大型应用拆分成多个小的模块。
例如,创建一个蓝图并在应用中注册:
python
from sanic import Blueprint
# 创建蓝图
bp = Blueprint("user")
@bp.route("/profile")
async def profile(request):
return json({"message": "User Profile"})
# 注册蓝图
app.blueprint(bp)
如何使用蓝图进行模块化开发
通过使用蓝图,可以将不同功能的路由分别放在不同的文件中,实现模块化管理。例如,将用户相关的路由放在 user.py
文件中,产品相关的路由放在 product.py
中。
python
# user.py
from sanic import Blueprint
bp = Blueprint("user")
@bp.route("/profile")
async def profile(request):
return json({"message": "User Profile"})
# main.py
from sanic import Sanic
from user import bp
app = Sanic("ModularApp")
app.blueprint(bp)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
异常处理
捕获全局异常
Sanic 允许全局捕获异常并进行自定义处理。可以使用 @app.exception
装饰器来捕获全局异常:
python
@app.exception(Exception)
async def handle_exception(request, exception):
return json({"error": str(exception)}, status=500)
自定义异常处理方法
也可以定义特定的异常处理函数,根据不同的错误类型做不同的处理。例如,处理 404
错误时返回自定义页面:
python
@app.exception(NotFound)
async def handle_not_found(request, exception):
return html("<h1>Page Not Found</h1>", status=404)