Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
aws avatar

Aws Sdk Python Usage

  • 3.8k installs
  • 2.2k repo stars
  • Updated August 4, 2026
  • aws/agent-toolkit-for-aws

aws-sdk-python-usage documents boto3 and botocore patterns for Python AWS SDK development.

About

The aws-sdk-python-usage skill governs Python code using boto3 and botocore for AWS services. It explains client versus resource interfaces, session and client creation with reuse outside loops, PascalCase API parameters, and typed client.exceptions over generic ClientError in business logic. Script structure keeps if __name__ main to a single main call with argparse and exit codes in main, never sys.exit in library functions. Pagination must use paginators with optional JMESPath search rather than manual NextToken loops. Waiters block until resources reach desired states. botocore.config.Config sets retries, timeouts, and pool sizes. Logging uses boto3.set_stream_logger or botocore session file loggers for wire debug. Common pitfall: ClientError imports from botocore.exceptions not boto3.exceptions. Service-specific references for S3 and DynamoDB must be loaded when those services appear. The skill forbids emojis in code, comments, or output while active.

  • Choose boto3 client for full API or resource for S3 and DynamoDB OO style.
  • Reuse one client per service; do not create clients inside loops.
  • Catch typed client.exceptions only with actionable handling.
  • Use paginators and waiters instead of manual token or poll loops.
  • Load references/s3.md and references/dynamodb.md when those services appear.

Aws Sdk Python Usage by the numbers

  • 3,835 all-time installs (skills.sh)
  • +493 installs in the week ending Aug 4, 2026 (Skillselion tracking)
  • Ranked #11 of 290 Python skills by installs in the Skillselion catalog
  • Security screen: LOW risk (skills.sh audit)
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
At a glance

aws-sdk-python-usage capabilities & compatibility

Capabilities
client versus resource selection guidance · session creation and client reuse rules · typed exception handling and main script structu · paginator, waiter, and config configuration patt · mandatory s3 and dynamodb reference loading
Use cases
api development · devops
Pricing
Bring your own API key
From the docs

What aws-sdk-python-usage says it does

Do not create clients inside loops
SKILL.md
npx skills add https://github.com/aws/agent-toolkit-for-aws --skill aws-sdk-python-usage

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs3.8k
repo stars2.2k
Security audit3 / 3 scanners passed
Last updatedAugust 4, 2026
Repositoryaws/agent-toolkit-for-aws

How should Python code use boto3 for clients, errors, pagination, and AWS service calls?

Write correct boto3 and botocore Python patterns for clients, sessions, errors, pagination, waiters, and service-specific S3 and DynamoDB usage.

Who is it for?

Python scripts or services importing boto3 or botocore for AWS operations.

Skip if: Skip for non-Python AWS work or infrastructure-as-code without application SDK code.

When should I use this skill?

Python imports boto3, uses S3, DynamoDB, Lambda, or user asks AWS operations in Python.

What you get

Correct client lifecycle, error handling, pagination, and service-specific patterns in Python.

  • boto3 client Config with retries and service-specific settings

By the numbers

  • Documents 3 retry modes: legacy, standard, and adaptive
  • Example uses total_max_attempts of 2 for one retry after the first try

Files

SKILL.mdMarkdownGitHub ↗
Do not use emojis in any code, comments, or output when this skill is active.

AWS SDK for Python (boto3)

boto3 is the high-level Python SDK for AWS. It wraps botocore (the low-level SDK) and provides two distinct interfaces: clients (low-level, 1:1 API mapping) and resources (high-level, object-oriented). Understanding which to use and when is essential.

Client vs Resource

Clients map directly to AWS service APIs. Every service has a client. Responses are plain dicts.

Resources provide an object-oriented interface with attributes and actions. Only some services have resources (S3, DynamoDB, EC2, IAM, SQS, SNS, CloudFormation, CloudWatch, Glacier). Resources auto-marshal types (especially useful for DynamoDB).

import boto3

# Client - low-level, all services
s3_client = boto3.client("s3")
response = s3_client.list_buckets()
buckets = response["Buckets"]  # plain dicts

# Resource - high-level, select services
s3_resource = boto3.resource("s3")
for bucket in s3_resource.buckets.all():
    print(bucket.name)  # attribute access, not dict keys

Use clients when you need full API coverage or the service has no resource interface. Use resources when they exist and simplify your code (especially DynamoDB and S3).

Session and Client Creation

import boto3

# Default session implicitly created
client = boto3.client("s3")
resource = boto3.resource("dynamodb")

# Explicit session use when you need to customize how
# clients are created, use an explicit profile, etc.
session = boto3.Session(
    profile_name="my-profile",
    region_name="us-west-2",
)
client = session.client("s3")

Do not create clients inside loops - reuse a single client instance. Clients are thread safe and can be shared across threads once they're instantiated.

Making API Calls

# Client - pass parameters as keyword arguments, get dicts back
response = client.get_object(Bucket="my-bucket", Key="my-key")
data = response["Body"].read()

# Resource - use object methods and attributes
obj = s3_resource.Object("my-bucket", "my-key")
response = obj.get()
data = response["Body"].read()

Parameter names match the exact casing of the AWS API, which is typically PascalCase, not snake\_case.

Error Handling

Only catch exceptions when you have something actionable to do - return a fallback value, retry, take a different code path. Catching an exception just to print it and swallow it is wrong: it hides the real error and prevents callers from reacting. Let exceptions propagate by default.

When you do catch, prefer typed exceptions on the client over generic ClientError with string code matching through the client.exceptions attribute:

lambda_client = boto3.client("lambda")

def get_function_config(name: str) -> dict | None:
    """Return function configuration, or None if it doesn't exist."""
    try:
        return lambda_client.get_function_configuration(FunctionName=name)
    except lambda_client.exceptions.ResourceNotFoundException:
        return None  # actionable: convert missing function to None
    # Everything else propagates - caller or main() handles it

Use generic ClientError only as a catch-all in a top-level error handler, not in business logic functions. It lives in botocore, not boto3:

from botocore.exceptions import ClientError

def main() -> int:
    try:
        result = do_the_work()
        print(result)
        return 0
    except ClientError as e:
        print(f"Error: {e}", file=sys.stderr)
        return 1

For the full error hierarchy and botocore exceptions, see references/error-handling.md.

Script Structure

When asked to write a script that uses boto3 or botocore, keep if __name__ == "__main__" to a single function call. Argument parsing, error presentation, and exit codes belong in main(), not scattered across business logic functions:

def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("bucket")
    args = parser.parse_args()

    try:
        do_the_work(args.bucket)
        return 0
    except ClientError as e:
        print(f"Error: {e}", file=sys.stderr)
        return 1

if __name__ == "__main__":
    sys.exit(main())

Never call sys.exit() from a business logic function -- it makes the function untestable and unusable as a library. Raise an exception or return an error value instead, and let main() decide how to present it.

Pagination

Never manually loop with NextToken -- use paginators. When you only need specific fields, use .search() with a JMESPath expression to extract and flatten across pages:

paginator = iam.get_paginator("list_users")
for name in paginator.paginate().search("Users[].UserName"):
    print(name)

# Filter and project
for arn in paginator.paginate().search("Users[?Path == '/admin/'][].Arn"):
    print(arn)

When you need the full response object per item, or need per-page control (e.g. counting pages, batching by page), iterate pages directly:

for page in paginator.paginate():
    for user in page.get("Users", []):
        process(user)

For more details on pagination, see: references/pagination.md.

Waiters

Wait for a resource to reach a desired state:

waiter = client.get_waiter("bucket_exists")
waiter.wait(
    Bucket="my-bucket",
    WaiterConfig={"Delay": 5, "MaxAttempts": 20},
)

For more details on waiters, see references/waiters.md.

Client Configuration

Use botocore.config.Config for retries, timeouts, and connection pool settings, etc.:

from botocore.config import Config

config = Config(
    retries={"total_max_attempts": 2, "mode": "adaptive"},
    connect_timeout=5,
    read_timeout=10,
    max_pool_connections=50,
)
client = boto3.client("s3", config=config)

When creating custom configuration for a client, see references/configuration.md.

Logging

Both boto3 and botocore use the standard library logging module. You can configure logging through the standard logging APIs, or you can use helpers provided by boto3 and botocore for convenience:

# Quick: log all botocore wire-level details to stderr
boto3.set_stream_logger("")  # root logger -- everything
boto3.set_stream_logger("botocore")  # just botocore

# Botocore, log all botocore details
import logging

from botocore.session import Session

session = Session()

session.set_stream_logger('botocore', logging.DEBUG)
# OR: Configure logging to a file.
session.set_file_logger(logging.DEBUG, '/tmp/botocore.log')

set_stream_logger(name, level=logging.DEBUG) adds a StreamHandler to the named logger. This is the idiomatic way to get request/response debug output from the SDK.

Common Issues

Issue: ClientError import location

Wrong: from boto3.exceptions import ClientError Right: from botocore.exceptions import ClientError

Service specific customizations

When writing any Python code that uses the following services, you MUST load these additional reference files for best practices and custom high level APIs:

  • S3 - you MUST load references/s3.md.
  • Dynamodb - you MUST load references/dynamodb.md.

References

  • Client configuration (retries, timeouts, endpoints): references/configuration.md
  • Credentials and sessions: references/credentials.md
  • Error handling patterns: references/error-handling.md
  • Pagination: references/pagination.md
  • Waiters: references/waiters.md
  • S3 transfers and presigned URLs: references/s3.md
  • DynamoDB operations: references/dynamodb.md

Related skills

How it compares

Pick aws-sdk-python-usage for application-level boto3 client tuning; use IaC skills when infrastructure—not SDK calls—defines AWS resources.

FAQ

Client or resource for DynamoDB?

Resources simplify marshalling when available; clients give full API coverage.

Where does ClientError import from?

from botocore.exceptions import ClientError, not boto3.exceptions.

When must I load S3 or DynamoDB references?

Whenever Python code uses those services; the skill requires loading their reference files.

Is Aws Sdk Python Usage safe to install?

skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.

Pythonbackendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.