Python编程:Sanic和jsonrpc库

使用 Sanic 框架开发 Web 和 WebSocket 应用

Sanic 是一个基于 Python 的异步 Web 框架,以下是使用 SanicjsonWebSocket 和 Request 的完整指南:

1. 安装 Sanic

首先安装 Sanic:

pip install sanic -i https://pypi.tuna.tsinghua.edu.cn/simple

推荐安装最新版本(当前 >=21.12+):

pip install --upgrade sanic -i https://pypi.tuna.tsinghua.edu.cn/simple

2. 基本 HTTP 服务器示例

from sanic import Sanic, json as jsonify, Request

app = Sanic("MyApp")

@app.route("/")
async def hello(request: Request):
    return jsonify({"message": "Hello Sanic!"})

@app.route("/user/<user_id:int>")
async def get_user(request: Request, user_id: int):
    return jsonify({"user_id": user_id, "name": "John"})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000, debug=True)

3. WebSocket 示例

from sanic import Websocket

@app.websocket("/ws")
async def chat(request: Request, ws: Websocket):
    while True:
        data = await ws.recv()
        await ws.send(f"Server received: {data}")

4. 完整功能示例

from sanic import Sanic, json as jsonify, Websocket, Request
from sanic.response import text

app = Sanic("AdvancedExample")

# 中间件示例
@app.middleware("request")
async def auth_middleware(request: Request):
    if request.token != "secret":
        return jsonify({"error": "Unauthorized"}, status=401)

# REST API 路由
@app.route("/api/data", methods=["GET", "POST"])
async def handle_data(request: Request):
    if request.method == "GET":
        return jsonify({"data": [1, 2, 3]})
    
    # POST 请求处理
    payload = request.json
    return jsonify({"received": payload}, status=201)

# WebSocket 聊天室
@app.websocket("/chat")
async def chat_handler(request: Request, ws: Websocket):
    await ws.send("Welcome to chat room!")
    
    while True:
        message = await ws.recv()
        if message == "exit":
            break
        await ws.send(f"You said: {message}")

# 文件上传
@app.route("/upload", methods=["POST"])
async def upload_file(request: Request):
    upload_file = request.files.get("file")
    if upload_file:
        return text(f"Received {upload_file.name}")
    return text("No file uploaded", status=400)

if __name__ == "__main__":
    app.run(
        host="0.0.0.0",
        port=8000,
        workers=4,
        access_log=True,
        debug=True
    )

5. 关键组件详解

5.1 Request 对象

@app.route("/info")
async def show_request_info(request: Request):
    return jsonify({
        "method": request.method,
        "url": request.url,
        "headers": dict(request.headers),
        "query": request.args,
        "body": request.json  # 自动解析 JSON 体
    })

5.2 WebSocket 通信

@app.websocket("/echo")
async def echo_server(request: Request, ws: Websocket):
    async for msg in ws:
        if msg == "ping":
            await ws.send("pong")
        else:
            await ws.send(f"Echo: {msg}")

5.3 JSON 响应

@app.route("/user")
async def get_current_user(request: Request):
    user = {
        "id": 123,
        "name": "Alice",
        "email": "alice@example.com"
    }
    return jsonify(user, status=200, headers={"X-Custom": "value"})

6. 高级功能

6.1 蓝图 (Blueprints)

from sanic import Blueprint

auth_bp = Blueprint("auth", url_prefix="/auth")

@auth_bp.route("/login")
async def login(request: Request):
    return jsonify({"token": "abc123"})

app.blueprint(auth_bp)

6.2 后台任务

@app.route("/start-task")
async def start_task(request: Request):
    async def background_task():
        await asyncio.sleep(10)
        print("Task completed")
    
    request.add_task(background_task)
    return text("Task started")

6.3 信号处理

from sanic.signals import Event

@app.signal(Event.HTTP_LIFECYCLE_BEGIN)
async def on_request_start(request: Request):
    print(f"Request started: {request.url}")

7. 运行与部署

开发模式运行:

python app.py

生产部署(使用 sanic CLI):

sanic app:app --host=0.0.0.0 --port=8000 --workers=8

使用 Gunicorn(多进程):

gunicorn app:app --worker-class sanic.worker.GunicornWorker

8. 注意事项

  1. 异步上下文:所有处理函数必须是 async 函数

  2. Python 版本:需要 Python 3.8+

  3. 性能调优

    • 调整 workers 数量(通常为 CPU 核心数)

    • 对于 CPU 密集型任务,考虑使用 uvloop

      pip install uvloop

      然后在代码中添加:

      app.run(..., fast=True)

Sanic 是构建高性能 Python Web 应用的优秀选择,特别适合需要异步处理和 WebSocket 功能的场景。

使用 jsonrpc 库实现 JSON-RPC 服务

jsonrpc 是一个用于实现 JSON-RPC 2.0 协议的 Python 库。

1. 安装 jsonrpc 库

pip install jsonrpcclient jsonrpcserver -i https://pypi.tuna.tsinghua.edu.cn/simple

或者安装经典版本(不推荐,可能不兼容 Python 3.10+):

pip install jsonrpc==1.12.3 -i https://pypi.tuna.tsinghua.edu.cn/simple

2. 基本服务端实现

from jsonrpc import JSONRPCResponseManager, Dispatcher
from werkzeug.wrappers import Request, Response

# 创建方法调度器
dispatcher = Dispatcher()

# 注册方法
@dispatcher.add_method
def add(a, b):
    return a + b

@dispatcher.add_method
def greet(name):
    return f"Hello, {name}!"

# 创建JSON-RPC服务端点
@Request.application
def application(request):
    response = JSONRPCResponseManager.handle(
        request.data, dispatcher
    )
    return Response(response.json, mimetype='application/json')

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4000, application)

3. 现代实现方式(推荐)

3.1 使用 jsonrpcserver

from jsonrpcserver import method, serve

@method
def add(a, b):
    return a + b

@method
def greet(name):
    return f"Hello, {name}!"

if __name__ == "__main__":
    serve(port=5000)

3.2 异步版本

from jsonrpcserver import method, async_dispatch
from aiohttp import web

@method
async def add(a, b):
    return a + b

async def handle(request):
    return web.Response(
        text=await async_dispatch(await request.text()),
        content_type="application/json"
    )

app = web.Application()
app.router.add_post("/", handle)

web.run_app(app, port=5000)

4. 客户端实现

4.1 基本客户端

import requests
import json

def rpc_call(url, method, params=None):
    payload = {
        "jsonrpc": "2.0",
        "method": method,
        "params": params or [],
        "id": 1
    }
    response = requests.post(url, json=payload).json()
    return response.get("result")

# 使用示例
result = rpc_call("http://localhost:4000", "add", [2, 3])
print(result)  # 输出: 5

4.2 使用 jsonrpcclient

from jsonrpcclient import request

response = request("http://localhost:4000", "greet", {"name": "Alice"})
print(response.data.result)  # 输出: "Hello, Alice!"

5. 高级功能

5.1 错误处理

from jsonrpc import JSONRPCResponseManager, Dispatcher
from jsonrpc.exceptions import JSONRPCDispatchException

dispatcher = Dispatcher()

@dispatcher.add_method
def divide(a, b):
    if b == 0:
        raise JSONRPCDispatchException(
            code=-32000,
            message="Division by zero",
            data={"param_b": b}
        )
    return a / b

5.2 批量请求

batch_request = [
    {"jsonrpc": "2.0", "method": "add", "params": [2, 3], "id": 1},
    {"jsonrpc": "2.0", "method": "greet", "params": ["Bob"], "id": 2}
]

response = requests.post("http://localhost:4000", json=batch_request).json()

6. 与 Web 框架集成

6.1 Flask 集成

from flask import Flask, request
from jsonrpc import JSONRPCResponseManager

app = Flask(__name__)

@app.route("/api", methods=["POST"])
def rpc_server():
    manager = JSONRPCResponseManager()
    return manager.handle(request.data, dispatcher)

6.2 Sanic 集成

from sanic import Sanic, json
from jsonrpc import JSONRPCResponseManager

app = Sanic("RPCService")

@app.post("/api")
async def rpc_handler(request):
    manager = JSONRPCResponseManager()
    response = manager.handle(request.body, dispatcher)
    return json(response.data)

7. 注意事项

  1. 版本兼容性

    • 经典 jsonrpc 库 (1.x) 可能不兼容 Python 3.10+

    • 推荐使用 jsonrpcserver 和 jsonrpcclient 替代

  2. 安全性

    • 始终验证输入参数

    • 考虑添加认证中间件

  3. 性能优化

    • 对于高负载服务,考虑使用异步实现

    • 使用连接池管理客户端连接

  4. 调试工具

    • 使用 Postman 或 curl 测试端点:

      curl -X POST http://localhost:4000 \
           -H "Content-Type: application/json" \
           -d '{"jsonrpc":"2.0","method":"add","params":[2,3],"id":1}'

JSON-RPC 是构建轻量级 API 服务的优秀协议,特别适合需要简单、标准化通信的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值