К основному содержанию
правило

sanic — правило для Cursor: что делает и как установить

Задаёт стандарты асинхронной разработки на Sanic в Python: фабрика create_app, Blueprints, вынос блокирующих вызовов в воркеры и запуск задач в фоне.

Установить в Cursor · Вручную: положить файлы Все способы и платформы ↓
.cursor/rules/sanic.mdc
Открыть на GitHub

Что делает sanic

Правило определяет структуру проектов на Sanic для файлов с маской **/*.py. Вместо глобального экземпляра приложения и монолитного файла оно требует собирать проект через функцию-фабрику create_app и модули Blueprint. Конфигурация выносится в отдельный класс Config. Ресурсы вроде пула соединений с базой данных инициализируются в слушателе @app.listener("before_server_start") и сохраняются в контексте app.ctx.

Главное требование — поддерживать цикл событий свободным. Синхронные паузы вроде time.sleep или забытый await блокируют работу всего сервера и роняют пропускную способность. Для тяжёлых вычислений и блокирующего ввода-вывода правило предписывает использовать ThreadPoolExecutor вместе с request.app.loop.run_in_executor. Фоновые операции, не влияющие на ответ клиенту, запускаются через request.app.add_task.

Какие задачи решает

  • структурировать приложение Sanic через фабрику create_app и Blueprints
  • вынести блокирующий ввод-вывод в отдельный ThreadPoolExecutor
  • настроить подключение к базе данных через слушатель before_server_start
  • запускать фоновые операции без ожидания ответа через app.add_task

Примеры запросов агенту

  • Разбей эндпоинты пользователей на отдельный Blueprint в Sanic с фабрикой приложений
  • Сделай эндпоинт регистрации, который отправляет письмо через app.add_task
  • Вынеси тяжёлую синхронную функцию обработки данных в ThreadPoolExecutor через run_in_executor

Как установить sanic

Вручную: положить файлы

.cursor/rules/sanic.mdc

Во frontmatter: description, globs, alwaysApply

По шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules

Вопросы о sanic

Как установить sanic в Cursor?

Сохраните файл правила по пути .cursor/rules/sanic.mdc в корне вашего проекта. Настройка начнёт действовать автоматически при редактировании файлов Python.

Что делает правило sanic?

Оно настраивает ассистента на соблюдение асинхронных практик Sanic: использование фабрики приложений, изоляцию конфигурации, регистрацию Blueprints и предотвращение блокировок event loop.

Как правило рекомендует обрабатывать тяжёлые синхронные функции?

Правило требует направлять блокирующий ввод-вывод и синхронные вызовы в пул потоков ThreadPoolExecutor с помощью вызова request.app.loop.run_in_executor.

Исходный текст

sanic.mdc · CC0-1.0
---
description: Definitive guidelines for building high-performance, maintainable, and secure Sanic applications using modern Python async best practices.
globs: **/*.py
---
# sanic Best Practices

Sanic is built for speed and scalability. To harness its full power and maintain a robust codebase, adhere strictly to these guidelines.

## 1. Code Organization and Structure

Always structure your Sanic application using the **factory pattern** and **Blueprints** for modularity. Keep configuration separate.

❌ BAD: Global app instance, monolithic file
```python
# app.py
from sanic import Sanic, response

app = Sanic("my_app") # Global instance is hard to test and configure

@app.route("/")
async def hello_world(request):
    return response.json({"message": "Hello!"})

# Configuration directly in code
app.config.DB_URL = "sqlite:///db.sqlite"
```

✅ GOOD: Factory pattern, Blueprints, external config
```python
# config.py
import os

class Config:
    DB_URL = os.getenv("DB_URL", "sqlite:///db.sqlite")
    SECRET_KEY = os.getenv("SECRET_KEY", "super-secret-key")

# app.py
from sanic import Sanic
from .config import Config
from .blueprints.users import bp as users_bp
from .blueprints.auth import bp as auth_bp

def create_app() -> Sanic:
    app = Sanic("my_app")
    app.config.update(Config.__dict__) # Load config from a dedicated object

    app.blueprint(users_bp)
    app.blueprint(auth_bp)

    # Add listeners, middleware, etc. here
    @app.listener("before_server_start")
    async def setup_db(app, loop):
        # Example: Initialize a database connection pool
        app.ctx.db = "AsyncDatabaseConnection" # Placeholder for actual DB setup
        print(f"Connecting to DB: {app.config.DB_URL}")

    return app

# blueprints/users.py
from sanic import Blueprint, Request, response
from typing import Dict, Any

bp = Blueprint("users", url_prefix="/users")

@bp.route("/", methods=["GET"])
async def get_all_users(request: Request) -> response.HTTPResponse:
    # Simulate async DB call using app.ctx.db
    # await request.app.ctx.db.fetch_all("SELECT * FROM users")
    return response.json([{"id": 1, "name": "Alice"}])

@bp.route("/<user_id:int>", methods=["GET"])
async def get_user(request: Request, user_id: int) -> response.HTTPResponse:
    # Simulate async DB call
    # user = await request.app.ctx.db.fetch_one(f"SELECT * FROM users WHERE id={user_id}")
    user = {"id": user_id, "name": "Alice"} # Placeholder
    if user:
        return response.json(user)
    return response.json({"message": "User not found"}, status=404)
```

## 2. Common Patterns and Anti-patterns

**Never block the event loop.** Sanic's performance hinges on non-blocking I/O. Offload heavy computations or blocking I/O to background tasks or external services.

❌ BAD: Blocking I/O in a handler
```python
import time
from sanic import Request, response

@app.route("/blocking")
async def blocking_endpoint(request: Request) -> response.HTTPResponse:
    time.sleep(5) # Blocks the entire event loop!
    return response.json({"message": "Done after 5s"})
```

✅ GOOD: Use `asyncio.sleep` or offload blocking work
```python
import asyncio
from sanic import Request, response
from concurrent.futures import ThreadPoolExecutor # For I/O-bound blocking tasks
from typing import Dict, Any

# Use a global executor or pass it via app.ctx
executor = ThreadPoolExecutor()

def heavy_blocking_io_task(data: int) -> Dict[str, int]:
    # Simulate I/O-bound blocking task
    time.sleep(2)
    return {"result": data * 2}

@app.route("/non_blocking")
async def non_blocking_endpoint(request: Request) -> response.HTTPResponse:
    await asyncio.sleep(0.1) # Yields control, doesn't block
    return response.json({"message": "Done quickly"})

@app.route("/heavy_io_task")
async def heavy_io_task_endpoint(request: Request) -> response.HTTPResponse:
    data = request.json.get("value", 10) if request.json else 10
    # Run blocking I/O in a thread pool
    result = await request.app.loop.run_in_executor(executor, heavy_blocking_io_task, data)
    return response.json(result)
```

## 3. Performance Considerations

Leverage Sanic's async nature. Use `app.add_task` for fire-and-forget background operations.

✅ GOOD: Background tasks for non-critical work
```python
from sanic import Sanic, Request, response
import asyncio

app = Sanic("perf_app")

async def send_email_async(recipient: str, subject: str, body: str):
    await asyncio.sleep(2) # Simulate I/O for sending email
    print(f"Email sent to {recipient}: {subject}")

@app.route("/signup", methods=["POST"])
async def signup(request: Request) -> response.HTTPResponse:
    user_data = request.json
    # ... save user to DB ...

    # Add email sending to background task, doesn't block response
    request.app.add_task(send_email_async(user_data["email"], "Welcome!", "Thanks for signing up!"))

    return response.json({"message": "User signed up successfully"}, status=201)
```

## 4. Common Pitfalls and Gotchas

Forgetting `await` is a common mistake that leads to unhandled coroutines and unexpected behavior. Always `await` coroutine calls.

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Похожие правила IDE

Все правила IDE по теме «Бэкенд и API» →
async-python-patterns Seth Hobson Скилл помогает писать асинхронный Python-код с asyncio, async/await и конкурентными задачами. Пригодится для API и приложений с большим числом I/O-операций. CX Codex 18 055установок python-pro VoltAgent Community Субагент пишет типобезопасный Python-код для веб API, системных утилит и сложных приложений. Пригодится для async-задач и проектов с высокими требованиями к типам. 11 689установок ccxt-python ccxt Скилл помогает писать Python-код для работы с криптобиржами через библиотеку CCXT. Поддерживает REST и WebSocket API в синхронном и асинхронном режимах. CX Codex +1 2 100установок python-patterns davila7 Скилл задаёт правила проектирования на Python: помогает выбрать фреймворк, настроить асинхронный стек, схемы Pydantic и разметку типов. 1 135установок asyncio-concurrency-patterns manutej Скилл по конкурентности в Python: event loop, корутины, задачи, семафоры и блокировки. Пригодится, когда пишешь асинхронный сервис или клиент. CX Codex +1 489установок fastapi-development manutej Набор инструкций для проектирования API на Python с асинхронными эндпоинтами, валидацией через Pydantic и маршрутизацией запросов. CX Codex +1 451установок

Из того же набора240

Весь набор →
scrapy Правило с набором практик для Scrapy: структура проекта, items, pipelines, middlewares. Пригодится, когда агент пишет парсеры на Python. ★ 3 580звёзд репо scipy Набор правил для написания научного кода на SciPy в Cursor: оформление docstrings, именованные аргументы и вычисления. ★ 3 580звёзд репо scikit-learn Правило направляет Cursor при работе с Python-кодом scikit-learn: помогает оформлять предобработку и модели через Pipeline и не допускать утечки данных. ★ 3 580звёзд репо scikit-image Правило задаёт команде единый стиль работы с scikit-image: неизменяемость входных массивов, float-диапазон [0, 1], векторизация вместо циклов по пикселям. ★ 3 580звёзд репо rust Правило задаёт стиль для Rust-кода: структуру модулей, типобезопасные паттерны, обработку ошибок и тесты. Подключается ко всем файлам проекта. ★ 3 580звёзд репо ruby Правило для Cursor задаёт команде единый стиль Ruby: RuboCop, соглашения Rails, работа с N+1 и защита от SQL-инъекций. ★ 3 580звёзд репо ros Задаёт стандарты разработки пакетов ROS 2 на C++ и Python в Cursor. Помогает настроить линтеры ament, компоновку нод и многопоточные исполнители. ★ 3 580звёзд репо rocket Правило задаёт рекомендации по структуре и разработке backend-сервисов на Rocket: от маршрутов и валидации до асинхронных обработчиков и ошибок. ★ 3 580звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой