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

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

Направляет ассистента писать надёжный код на Python с boto3: переиспользовать клиенты, разбивать запросы на пачки и выбирать готовые пагинаторы вместо ручных циклов.

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

Что делает boto3

Правило настраивает генерацию Python-кода под AWS SDK. Файл привязан к маске **/*.py и требует выносить клиенты на уровень модуля или передавать их через внедрение зависимостей. Создавать экземпляры boto3.client внутри циклов или часто вызываемых функций запрещено, так как постоянная инициализация создаёт лишнюю нагрузку на обновление учётных данных и ломает пул соединений.

В инструкциях разграничены низкоуровневые клиенты и ресурсы. Для типовых задач в S3, EC2 или DynamoDB агент задействует boto3.resource, чтобы не писать ручные циклы обхода. Если нужен низкоуровневый клиент, правило требует вызывать get_paginator вместо ручных циклов с NextToken, а также группировать вызовы в батчи — например, пачками до 10 записей для очередей SQS.

В примерах активно используются аннотации типов из библиотек mypy_boto3_*. Для работы статической типизации эти пакеты-заглушки нужно заранее добавить в проект.

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

  • устранить пересоздание клиентов AWS в циклах
  • заменить ручные циклы с NextToken на встроенные пагинаторы
  • упаковать отправку сообщений в SQS пачками до 10 штук
  • настроить строгую типизацию вызовов boto3 через mypy_boto3

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

  • Напиши класс S3Manager для работы с бакетами с переиспользуемым клиентом и типами mypy.
  • Сделай функцию пакетной отправки сообщений в очередь SQS.
  • Получи список идентификаторов инстансов EC2 через пагинатор boto3.

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

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

.cursor/rules/boto3.mdc

Во frontmatter: description, globs, alwaysApply

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

Вопросы о boto3

Как установить правило boto3 в Cursor?

Создайте файл .cursor/rules/boto3.mdc в корне проекта и добавьте в него содержимое правила.

На какие файлы действует это правило?

В конфигурации правила указан шаблон **/*.py. Cursor применяет эти инструкции при редактировании любых файлов Python в репозитории.

В каких случаях инструкция советует выбирать resources вместо clients?

Ресурсы рекомендуются для сервисов вроде S3 или EC2, когда их объектная модель и автоматическая пагинация коллекций сокращают шаблонный код.

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

boto3.mdc · CC0-1.0
---
description: This rule file guides developers on writing idiomatic, high-performance, and type-safe boto3 code, emphasizing client reuse, proper pagination, batch operations, and robust testing strategies.
globs: **/*.py
---
# boto3 Best Practices

Boto3 is the definitive Python SDK for AWS. Mastering it means writing code that is performant, maintainable, and resilient. This guide outlines the essential patterns and anti-patterns for modern `boto3` development.

## 1. Client/Resource Management & Reuse

Never instantiate `boto3` clients or resources inside performance-critical loops or frequently called functions. Reusing client objects reduces credential churn, improves connection pooling, and significantly boosts performance.

### ✅ GOOD: Module-level or Dependency Injected Clients

Instantiate clients/resources once per module or inject them via a wrapper class.

```python
# my_aws_service.py
import boto3
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from mypy_boto3_s3.client import S3Client
    from mypy_boto3_s3.service_resource import S3ServiceResource

# Module-level client/resource for simple cases
S3_CLIENT: S3Client = boto3.client("s3", region_name="us-east-1")
S3_RESOURCE: S3ServiceResource = boto3.resource("s3", region_name="us-east-1")

class S3Manager:
    """Manages S3 operations with a reusable client."""
    def __init__(self, s3_client: S3Client = S3_CLIENT):
        self._s3_client = s3_client

    def list_my_buckets(self) -> list[str]:
        response = self._s3_client.list_buckets()
        return [b["Name"] for b in response.get("Buckets", [])]

# In another part of your application:
manager = S3Manager()
buckets = manager.list_my_buckets()
```

### ❌ BAD: Repeated Client Instantiation

Avoid creating new clients/resources for every operation.

```python
# my_aws_service_bad.py
import boto3

def get_bucket_names_bad() -> list[str]:
    # This creates a new client every time the function is called
    s3_client = boto3.client("s3", region_name="us-east-1")
    response = s3_client.list_buckets()
    return [b["Name"] for b in response.get("Buckets", [])]

# This is inefficient if called frequently
for _ in range(100):
    get_bucket_names_bad()
```

## 2. Choose Clients vs. Resources Wisely

`boto3` offers two interfaces:
*   **Clients**: Low-level, 1:1 mapping to AWS API calls. Provides fine-grained control.
*   **Resources**: Higher-level, object-oriented abstraction. Offers automatic pagination, attribute access, and simpler syntax for common operations.

### ✅ GOOD: Leverage Resources for Simplicity and Automation

Use resources when available and when their higher-level abstractions simplify your code (e.g., S3, EC2, DynamoDB).

```python
import boto3
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from mypy_boto3_s3.service_resource import Bucket, S3ServiceResource

S3_RESOURCE: S3ServiceResource = boto3.resource("s3")

def delete_all_objects_in_bucket(bucket_name: str) -> None:
    bucket: Bucket = S3_RESOURCE.Bucket(bucket_name)
    # Resource handles pagination automatically for collection iteration
    for obj in bucket.objects.all():
        obj.delete()
    print(f"Deleted all objects from {bucket_name}")

# Example usage:
# delete_all_objects_in_bucket("my-test-bucket")
```

### ❌ BAD: Over-complicating with Clients when Resources are Better

Manually handling tasks that resources automate.

```python
import boto3
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from mypy_boto3_s3.client import S3Client

S3_CLIENT: S3Client = boto3.client("s3")

def delete_all_objects_in_bucket_bad(bucket_name: str) -> None:
    # Requires manual pagination and object key extraction
    paginator = S3_CLIENT.get_paginator("list_objects_v2")
    for page in paginator.paginate(Bucket=bucket_name):
        objects_to_delete = [{"Key": obj["Key"]} for obj in page.get("Contents", [])]
        if objects_to_delete:
            S3_CLIENT.delete_objects(Bucket=bucket_name, Delete={"Objects": objects_to_delete})
    print(f"Deleted all objects from {bucket_name}")
```

## 3. Efficient Pagination

AWS APIs often return results in pages. Always use `boto3`'s built-in paginators or resource collections to iterate through all results.

### ✅ GOOD: Using Paginators or Resource Collections

```python
import boto3
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from mypy_boto3_ec2.client import EC2Client
    from mypy_boto3_ec2.service_resource import EC2ServiceResource, Instance

EC2_CLIENT: EC2Client = boto3.client("ec2")
EC2_RESOURCE: EC2ServiceResource = boto3.resource("ec2")

def list_all_instance_ids_client() -> list[str]:
    paginator = EC2_CLIENT.get_paginator("describe_instances")
    instance_ids = []
    for page in paginator.paginate():
        for reservation in page.get("Reservations", []):
            for instance in reservation.get("Instances", []):
                instance_ids.append(instance["InstanceId"])
    return instance_ids

def list_all_instance_ids_resource() -> list[str]:
    # Resource collections handle pagination automatically
    instance_ids = [instance.id for instance in EC2_RESOURCE.instances.all()]
    return instance_ids

# Example usage:
# print(list_all_instance_ids_client())
# print(list_all_instance_ids_resource())
```

### ❌ BAD: Manual Pagination Loops

This is error-prone and verbose.

```python
import boto3
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from mypy_boto3_ec2.client import EC2Client

EC2_CLIENT: EC2Client = boto3.client("ec2")

def list_all_instance_ids_manual_bad() -> list[str]:
    instance_ids = []
    next_token = None
    while True:
        kwargs = {"NextToken": next_token} if next_token else {}
        response = EC2_CLIENT.describe_instances(**kwargs)
        for reservation in response.get("Reservations", []):
            for instance in reservation.get("Instances", []):
                instance_ids.append(instance["InstanceId"])
        next_token = response.get("NextToken")
        if not next_token:
            break
    return instance_ids
```

## 4. Batch Operations

Always prefer batch operations when available to minimize API calls and improve efficiency.

### ✅ GOOD: Using Batch APIs

```python
import boto3
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from mypy_boto3_sqs.client import SQSClient

SQS_CLIENT: SQSClient = boto3.client("sqs")

def send_batch_messages(queue_url: str, messages: list[str]) -> None:
    entries = [{"Id": str(i), "MessageBody": msg} for i, msg in enumerate(messages)]
    # SQS allows up to 10 messages per batch
    for i in range(0, len(entries), 10):
        batch = entries[i:i+10]
        SQS_CLIENT.send_message_batch(QueueUrl=queue_url, Entries=batch)
    print(f"Sent {len(messages)} messages to {queue_url}")

# Example usage:
# send_batch_messages("https://sqs.us-east-1.amazonaws.com/123456789012/my-queue", ["msg1", "msg2", "msg3"])
```

### ❌ BAD: Looping Single Operations

```python
import boto3
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from mypy_boto3_sqs.client import SQSClient

SQS_CLIENT: SQSClient = boto3.client("sqs")

def send_individual_messages_bad(queue_url: str, messages: list[str]) -> None:
    for msg in messages:
        # Each message sends a separate API call
        SQS_CLIENT.send_message(QueueUrl=queue_url, MessageBody=msg)
    print(f"Sent {len(messages)} messages to {queue_url}")
```

## 5. Type Hinting with `boto3-stubs`

`boto3`'s dynamic nature makes static analysis challenging. Use `boto3-stubs` to enable precise type checking, catch errors early, and improve IDE autocomplete.

### ✅ GOOD: Fully Type-Hinted Boto3 Code

Install `boto3-stubs` (e.g., `pip install 'boto3-stubs[s3]' mypy`).

```python
from typing import TYPE_CHECKING
import boto3

if TYPE_CHECKING:
    from mypy_boto3_s3.client import S3Client
    from mypy_boto3_s3.type_defs import BucketTypeDef, ListBucketsOutputTypeDef

S3_CLIENT: S3Client = boto3.client("s3")

def get_s3_bucket_names() -> list[str]:
    response: ListBucketsOutputTypeDef = S3_CLIENT.list_buckets()
    buckets: list[BucketTypeDef] = response.get("Buckets", [])
    return [b["Name"] for b in buckets]

# Mypy will now correctly validate types and provide completions.
```

### ❌ BAD: Untyped Boto3 Code

This makes code harder to read, refactor, and debug.

```python
import boto3

s3_client = boto3.client("s3")

def get_s3_bucket_names_untyped():
    response = s3_client.list_buckets()
    # No type information here, relies on runtime inspection
    return [b["Name"] for b in response.get("Buckets", [])]
```

## 6. Robust Error Handling

Boto3 operations can fail. Always wrap calls in `try...except` blocks and catch specific `botocore.exceptions` for graceful degradation.

### ✅ GOOD: Specific Exception Handling

```python
import boto3
from botocore.exceptions import ClientError
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from mypy_boto3_s3.client import S3Client

S3_CLIENT: S3Client = boto3.client("s3")

def download_s3_object(bucket_name: str, key: str, local_path: str) -> bool:
    try:
        S3_CLIENT.download_file(bucket_name, key, local_path)
        print(f"Successfully downloaded {key} to {local_path}")
        return True
    except ClientError as e:
        if e.response["Error"]["Code"] == "404":
            print(f"Object {key} not found in bucket {bucket_name}.")
        elif e.response["Error"]["Code"] == "403":
            print(f"Permission denied to access {key} in bucket {bucket_name}.")
        else:
            print(f"An unexpected error occurred: {e}")
        return False
    except Exception as e:
        print(f"A general error occurred: {e}")
        return False

# Example usage:
# download_s3_object("my-test-bucket", "non-existent-file.txt", "/tmp/local.txt")
```

### ❌ BAD: Generic Exception Handling or No Handling

```python
import boto3
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from mypy_boto3_s3.client import S3Client

S3_CLIENT: S3Client = boto3.client("s3")

def download_s3_object_bad(bucket_name: str, key: str, local_path: str) -> None:
    try:
        S3_CLIENT.download_file(bucket_name, key, local_path)
    except Exception as e: # Too broad, hides specific issues
        print(f"An error occurred: {e}")
    # Or worse, no try/except at all.
```

## 7. Testing with `moto`

For unit and integration tests, `moto` provides a mock AWS environment, allowing you to test `boto3` interactions without hitting actual AWS services.

### ✅ GOOD: Using `moto` Decorators

```python
import boto3
import unittest
from moto import mock_aws

class TestS3Operations(unittest.TestCase):
    @mock_aws
    def test_create_and_list_bucket(self):
        s3_client = boto3.client("s3", region_name="us-east-1")
        bucket_name = "my-test-bucket"

        # Create a bucket
        s3_client.create_bucket(Bucket=bucket_name)

        # List buckets and assert
        response = s3_client.list_buckets()
        self.assertIn(bucket_name, [b["Name"] for b in response["Buckets"]])

        # Upload an object
        s3_client.put_object(Bucket=bucket_name, Key="test.txt", Body="Hello Moto!")

        # Download and verify
        response = s3_client.get_object(Bucket=bucket_name, Key="test.txt")
        self.assertEqual(response["Body"].read().decode("utf-8"), "Hello Moto!")

if __name__ == "__main__":
    unittest.main()
```

### ❌ BAD: Mocking `boto3` Internals Manually

While `unittest.mock` is powerful, mocking `boto3` at a low level is tedious and fragile.

```python
import boto3
import unittest
from unittest.mock import patch

class TestS3OperationsManualMock(unittest.TestCase):
    @patch("boto3.client")
    def test_create_bucket_manual_mock(self, mock_boto_client):
        # Configure the mock client to return specific values
        mock_s3_client = mock_boto_client.return_value
        mock_s3_client.list_buckets.return_value = {"Buckets": []}
        mock_s3_client.create_bucket.return_value = {} # Simulate success

        s3_client = boto3.client("s3") # This will now return our mock
        s3_client.create_bucket(Bucket="my-test-bucket")

        mock_s3_client.create_bucket.assert_called_once_with(Bucket="my-test-bucket")
        # This approach quickly becomes complex for more involved interactions.
```

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

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

Все правила IDE по теме «Облака: AWS, Azure, GCP» →
django-storages-s3 https://github.com/awais786 Скилл настраивает хранение статики и медиафайлов Django в AWS S3 через django-storages и boto3: словарь STORAGES, presigned-ссылки, CloudFront, IAM. CX Codex +1 900установок ministack-aws-emulator reason-machines Скилл помогает агенту поднять MiniStack — локальный эмулятор AWS для тестов с S3, SQS, DynamoDB и другими сервисами. CX Codex +1 790установок aws-lambda devops-skills Скилл помогает развёртывать функции AWS Lambda, настраивать триггеры S3 или SQS и организовывать канареечные релизы. CX Codex +1 321установок aws-sdk-python-usage aws Скилл задаёт правила кодинга на Python с библиотеками boto3 и botocore. Он подсказывает агенту, когда брать client или resource, как настраивать пагинацию и перехватывать ошибки AWS. CX Codex +1 7 800установок hf-cloud-python-env-setup huggingface Скилл разворачивает изолированное окружение Python для работы с AWS и SageMaker. Он помогает избежать сбоев из-за несовместимых версий Python и устаревшего SDK boto3. CX Codex +1 548установок aws-messaging-and-streaming aws Помогает агенту выбрать, чем двигать данные в AWS: очередью, шиной событий или журналом. Полезно до того, как вы зафиксируете SQS или Kinesis. CX Codex +1 8 100установок

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

Весь набор →
chakra-ui Правило для Cursor задаёт, как писать интерфейсы на Chakra UI v2: тема через токены, варианты компонентов через рецепты, стилевые пропсы вместо CSS. ★ 3 580звёзд репо c-sharp Задаёт правила оформления кода на C# для Cursor: от стиля Allman и именования сущностей до внедрения зависимостей и запрета блокирующих асинхронных вызовов. ★ 3 580звёзд репо bun Правило задаёт стиль JavaScript-кода в файлах .js и .jsx: предлагает использовать инструменты Bun, современные конструкции языка и понятную структуру проекта. ★ 3 580звёзд репо bottle Правило для Cursor задаёт структуру Bottle-проекта: модули вместо одного app.py, конфиг через app.config, валидация Pydantic. Пригодится, если пишете бэкенд на Bottle. ★ 3 580звёзд репо black Правило для Cursor задаёт единый стиль Python-кода с помощью Black. Оно помогает согласовать форматирование исходников и проверять его перед слиянием изменений. ★ 3 580звёзд репо behave Правило задаёт Cursor стандарты для BDD-тестов на behave: тонкие шаги, чистый Gherkin, фикстуры через environment.py. ★ 3 580звёзд репо beautifulsoup4 Задаёт стандарты парсинга HTML на Python: выбор lxml, работа с CSS-селекторами и валидация структур через Pydantic. ★ 3 580звёзд репо bash Правило задаёт стиль для Bash-скриптов: обработка ошибок, кавычки, переменные и структура кода. Подходит для проектов, где скрипты проходят через Cursor. ★ 3 580звёзд репо

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

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