← AWS CoreCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to AWS Core
Snapshot Sep 30, 2026 · 22:47 UTC · version 1.0.0
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"name": "aws-sdk-python-usage",
"description": "AWS SDK for Python (boto3/botocore) development patterns. You MUST use this skill when writing Python code that uses AWS services via boto3 or botocore. This includes creating service clients or resources, configuring sessions and credentials, handling errors with ClientError, using paginators and waiters, S3 file transfers and presigned URLs, DynamoDB table operations, and any boto3/botocore client configuration. Use this skill whenever Python code imports boto3 or botocore, or when the user asks about AWS operations in Python.",
"included_files": [
{
"relative_path": "references/configuration.md",
"size_in_bytes": 3835
},
{
"relative_path": "references/credentials.md",
"size_in_bytes": 3757
},
{
"relative_path": "references/dynamodb.md",
"size_in_bytes": 8578
},
{
"relative_path": "references/error-handling.md",
"size_in_bytes": 4561
},
{
"relative_path": "references/pagination.md",
"size_in_bytes": 3031
},
{
"relative_path": "references/s3.md",
"size_in_bytes": 5229
},
{
"relative_path": "references/waiters.md",
"size_in_bytes": 3422
}
],
"skill_md_contents": "---\nname: aws-sdk-python-usage\ndescription: |\n AWS SDK for Python (boto3/botocore) development patterns. You MUST use this skill when writing Python code that uses AWS services via boto3 or botocore. This includes creating service clients or resources, configuring sessions and credentials, handling errors with ClientError, using paginators and waiters, S3 file transfers and presigned URLs, DynamoDB table operations, and any boto3/botocore client configuration. Use this skill whenever Python code imports boto3 or botocore, or when the user asks about AWS operations in Python.\n---\n\n> Do not use emojis in any code, comments, or output when this skill is active.\n\n# AWS SDK for Python (boto3)\n\nboto3 is the high-level Python SDK for AWS. It wraps botocore (the low-level\nSDK) and provides two distinct interfaces: **clients** (low-level, 1:1 API\nmapping) and **resources** (high-level, object-oriented). Understanding which to\nuse and when is essential.\n\n## Client vs Resource\n\n**Clients** map directly to AWS service APIs. Every service has a client.\nResponses are plain dicts.\n\n**Resources** provide an object-oriented interface with attributes and actions.\nOnly some services have resources (S3, DynamoDB, EC2, IAM, SQS, SNS,\nCloudFormation, CloudWatch, Glacier). Resources auto-marshal types (especially\nuseful for DynamoDB).\n\n```python\nimport boto3\n\n# Client - low-level, all services\ns3_client = boto3.client(\"s3\")\nresponse = s3_client.list_buckets()\nbuckets = response[\"Buckets\"] # plain dicts\n\n# Resource - high-level, select services\ns3_resource = boto3.resource(\"s3\")\nfor bucket in s3_resource.buckets.all():\n print(bucket.name) # attribute access, not dict keys\n```\n\nUse clients when you need full API coverage or the service has no resource\ninterface. Use resources when they exist and simplify your code (especially\nDynamoDB and S3).\n\n## Session and Client Creation\n\n```python\nimport boto3\n\n# Default session implicitly created\nclient = boto3.client(\"s3\")\nresource = boto3.resource(\"dynamodb\")\n\n# Explicit session use when you need to customize how\n# clients are created, use an explicit profile, etc.\nsession = boto3.Session(\n profile_name=\"my-profile\",\n region_name=\"us-west-2\",\n)\nclient = session.client(\"s3\")\n```\n\nDo not create clients inside loops - reuse a single client instance. Clients\nare thread safe and can be shared across threads once they're instantiated.\n\n## Making API Calls\n\n```python\n# Client - pass parameters as keyword arguments, get dicts back\nresponse = client.get_object(Bucket=\"my-bucket\", Key=\"my-key\")\ndata = response[\"Body\"].read()\n\n# Resource - use object methods and attributes\nobj = s3_resource.Object(\"my-bucket\", \"my-key\")\nresponse = obj.get()\ndata = response[\"Body\"].read()\n```\n\nParameter names match the exact casing of the AWS API,\nwhich is typically PascalCase, not snake\\_case.\n\n## Error Handling\n\nOnly catch exceptions when you have something actionable to do - return a\nfallback value, retry, take a different code path. Catching an exception just to\nprint it and swallow it is wrong: it hides the real error and prevents callers\nfrom reacting. Let exceptions propagate by default.\n\nWhen you do catch, prefer typed exceptions on the client over generic\n`ClientError` with string code matching through the `client.exceptions`\nattribute:\n\n```python\nlambda_client = boto3.client(\"lambda\")\n\ndef get_function_config(name: str) -> dict | None:\n \"\"\"Return function configuration, or None if it doesn't exist.\"\"\"\n try:\n return lambda_client.get_function_configuration(FunctionName=name)\n except lambda_client.exceptions.ResourceNotFoundException:\n return None # actionable: convert missing function to None\n # Everything else propagates - caller or main() handles it\n```\n\nUse generic `ClientError` only as a catch-all in a top-level error handler, not\nin business logic functions. It lives in botocore, not boto3:\n\n```python\nfrom botocore.exceptions import ClientError\n\ndef main() -> int:\n try:\n result = do_the_work()\n print(result)\n return 0\n except ClientError as e:\n print(f\"Error: {e}\", file=sys.stderr)\n return 1\n```\n\nFor the full error hierarchy and botocore exceptions, see `references/error-handling.md`.\n\n## Script Structure\n\nWhen asked to write a script that uses `boto3` or `botocore`, keep `if __name__\n== \"__main__\"` to a single function call. Argument parsing, error presentation,\nand exit codes belong in `main()`, not scattered across business logic\nfunctions:\n\n```python\ndef main() -> int:\n parser = argparse.ArgumentParser()\n parser.add_argument(\"bucket\")\n args = parser.parse_args()\n\n try:\n do_the_work(args.bucket)\n return 0\n except ClientError as e:\n print(f\"Error: {e}\", file=sys.stderr)\n return 1\n\nif __name__ == \"__main__\":\n sys.exit(main())\n```\n\nNever call `sys.exit()` from a business logic function -- it makes the function\nuntestable and unusable as a library. Raise an exception or return an error\nvalue instead, and let `main()` decide how to present it.\n\n## Pagination\n\nNever manually loop with `NextToken` -- use paginators. When you only need\nspecific fields, use `.search()` with a JMESPath expression to extract and\nflatten across pages:\n\n```python\npaginator = iam.get_paginator(\"list_users\")\nfor name in paginator.paginate().search(\"Users[].UserName\"):\n print(name)\n\n# Filter and project\nfor arn in paginator.paginate().search(\"Users[?Path == '/admin/'][].Arn\"):\n print(arn)\n```\n\nWhen you need the full response object per item, or need per-page control (e.g.\ncounting pages, batching by page), iterate pages directly:\n\n```python\nfor page in paginator.paginate():\n for user in page.get(\"Users\", []):\n process(user)\n```\n\nFor more details on pagination, see: `references/pagination.md`.\n\n## Waiters\n\nWait for a resource to reach a desired state:\n\n```python\nwaiter = client.get_waiter(\"bucket_exists\")\nwaiter.wait(\n Bucket=\"my-bucket\",\n WaiterConfig={\"Delay\": 5, \"MaxAttempts\": 20},\n)\n```\n\nFor more details on waiters, see `references/waiters.md`.\n\n## Client Configuration\n\nUse `botocore.config.Config` for retries, timeouts, and connection pool\nsettings, etc.:\n\n```python\nfrom botocore.config import Config\n\nconfig = Config(\n retries={\"total_max_attempts\": 2, \"mode\": \"adaptive\"},\n connect_timeout=5,\n read_timeout=10,\n max_pool_connections=50,\n)\nclient = boto3.client(\"s3\", config=config)\n```\n\nWhen creating custom configuration for a client, see `references/configuration.md`.\n\n## Logging\n\nBoth boto3 and botocore use the standard library `logging` module. You can\nconfigure logging through the standard `logging` APIs, or you can use\nhelpers provided by boto3 and botocore for convenience:\n\n```python\n# Quick: log all botocore wire-level details to stderr\nboto3.set_stream_logger(\"\") # root logger -- everything\nboto3.set_stream_logger(\"botocore\") # just botocore\n\n# Botocore, log all botocore details\nimport logging\n\nfrom botocore.session import Session\n\nsession = Session()\n\nsession.set_stream_logger('botocore', logging.DEBUG)\n# OR: Configure logging to a file.\nsession.set_file_logger(logging.DEBUG, '/tmp/botocore.log')\n```\n\n`set_stream_logger(name, level=logging.DEBUG)` adds a\n`StreamHandler` to the named logger. This is the idiomatic way to get\nrequest/response debug output from the SDK.\n\n## Common Issues\n\n### Issue: ClientError import location\n\n**Wrong:** `from boto3.exceptions import ClientError`\n**Right:** `from botocore.exceptions import ClientError`\n\n## Service specific customizations\n\nWhen writing any Python code that uses the following services, you MUST load\nthese additional reference files for best practices and custom high level APIs:\n\n* S3 - you MUST load `references/s3.md`.\n* Dynamodb - you MUST load `references/dynamodb.md`.\n\n## References\n\n* Client configuration (retries, timeouts, endpoints): `references/configuration.md`\n* Credentials and sessions: `references/credentials.md`\n* Error handling patterns: `references/error-handling.md`\n* Pagination: `references/pagination.md`\n* Waiters: `references/waiters.md`\n* S3 transfers and presigned URLs: `references/s3.md`\n* DynamoDB operations: `references/dynamodb.md`\n"
}SHA-256: fcb24ad51f9a7fad1bc5a86efaf58498730347733d19511e8ecfbcff5a8ce6ed