Skip to content

How to define "snapshot" in python code

0

Hi re:Post! Thank you for your time and help!

I am testing a lambda function and am getting this error stack:

{
  "errorMessage": "name 'snapshot' is not defined",
  "errorType": "NameError",
  "requestId": "",
  "stackTrace": [
    "  File \"/var/lang/lib/python3.12/importlib/__init__.py\", line 90, in import_module\n    return _bootstrap._gcd_import(name[level:], package, level)\n",
    "  File \"<frozen importlib._bootstrap>\", line 1387, in _gcd_import\n",
    "  File \"<frozen importlib._bootstrap>\", line 1360, in _find_and_load\n",
    "  File \"<frozen importlib._bootstrap>\", line 1331, in _find_and_load_unlocked\n",
    "  File \"<frozen importlib._bootstrap>\", line 935, in _load_unlocked\n",
    "  File \"<frozen importlib._bootstrap_external>\", line 999, in exec_module\n",
    "  File \"<frozen importlib._bootstrap>\", line 488, in _call_with_frames_removed\n",
    "  File \"/var/task/lambda_function.py\", line 39, in <module>\n    snapshot_id = snapshot['DBSnapshotIdentifier']\n"
  ]
}

With the error being around line 39:

Error: "errorMessage": "name 'snapshot' is not defined",

Line39: "snapshot_id = snapshot['DBSnapshotIdentifier']"

Question: How should I define snapshot?

Here is the python code:

import boto3
import os
from datetime import datetime

# Define regions
# SOURCE_REGION = "us-west-1"  # N. California
SOURCE_REGION = "us-west-2"  # Oregon
DEST_REGION = "us-west-2"    # Oregon
NUM_SNAPSHOTS = 2            # Number of snapshots to process

def lambda_handler(event, context):
# Create RDS clients for both regions
    source_rds = boto3.client('rds', region_name=SOURCE_REGION)
    dest_rds = boto3.client('rds', region_name=DEST_REGION)

# Step 1: Delete oldest manual snapshots in destination region
    delete_oldest_snapshots(dest_rds, NUM_SNAPSHOTS)

# Step 2: Copy latest system snapshots from source to destination
    copy_latest_snapshots(source_rds, dest_rds, NUM_SNAPSHOTS)

    return {
'statusCode': 200,
'body': f'Successfully processed {NUM_SNAPSHOTS} snapshots'
}

def delete_oldest_snapshots(dest_rds, count):
# Get all manual snapshots in destination region
    response = dest_rds.describe_db_snapshots(SnapshotType='manual')

# Sort snapshots by creation time (oldest first)
    snapshots = sorted(response['DBSnapshots'], key=lambda s: s['SnapshotCreateTime'])

# Delete the oldest 'count' snapshots
    for i, snapshot in enumerate(snapshots):
        if i >= count:
            break

snapshot_id = snapshot['DBSnapshotIdentifier']
print(f"Deleting snapshot: {snapshot_id}")

try:
    dest_rds.delete_db_snapshot(DBSnapshotIdentifier=snapshot_id)
    print(f"Successfully deleted snapshot: {snapshot_id}")
except Exception as e:
    print(f"Error deleting snapshot {snapshot_id}: {str(e)}")

def copy_latest_snapshots(source_rds, dest_rds, count):
# Get all automated snapshots in source region
    response = source_rds.describe_db_snapshots(SnapshotType='automated')

# Sort snapshots by creation time (newest first)
snapshots = sorted(response['DBSnapshots'], 
key=lambda s: s['SnapshotCreateTime'], 
reverse=True)

# Get today's date for naming
today = datetime.now().strftime("%Y-%m-%d")

# Define the database names based on your example
#  "amgen", "alpine"
db_names = [
"demo", "drtest20240314"
]

# Copy the newest 'count' snapshots
for i, snapshot in enumerate(snapshots[:count]):
    if i >= count:
        break

source_snapshot_id = snapshot['DBSnapshotIdentifier']
db_instance_id = snapshot['DBInstanceIdentifier']

# Use the corresponding db name from the list if available
db_name = db_names[i] if i < len(db_names) else db_instance_id

# Create target snapshot name
target_snapshot_id = f"copy-rds-db-{db_name}-{today}"

print(f"Copying snapshot {source_snapshot_id} to {target_snapshot_id}")

try:
# Create ARN for source snapshot
    source_arn = f"arn:aws:rds:{SOURCE_REGION}:{snapshot['DBSnapshotArn'].split(':')[4]}:{source_snapshot_id}"

# Copy the snapshot
    dest_rds.copy_db_snapshot(
SourceDBSnapshotIdentifier=source_arn,
TargetDBSnapshotIdentifier=target_snapshot_id,
SourceRegion=SOURCE_REGION
)
    print(f"Successfully initiated copy of {source_snapshot_id} to {target_snapshot_id}")
except Exception as e:
    print(f"Error copying snapshot {source_snapshot_id}: {str(e)}")

Question: How should I define snapshot?

Best Regards,

Donald

asked 9 months ago96 views
3 Answers
1
Accepted Answer

Please try with the below snippet

def delete_oldest_snapshots(dest_rds, count): # Get all manual snapshots in destination region response = dest_rds.describe_db_snapshots(SnapshotType='manual')

# Sort snapshots by creation time (oldest first)
snapshots = sorted(response['DBSnapshots'], key=lambda s: s['SnapshotCreateTime'])

# Delete the oldest 'count' snapshots
for i, snapshot in enumerate(snapshots):
    if i >= count:
        break

    snapshot_id = snapshot['DBSnapshotIdentifier']
    print(f"Deleting snapshot: {snapshot_id}")

    try:
        dest_rds.delete_db_snapshot(DBSnapshotIdentifier=snapshot_id)
        print(f"Successfully deleted snapshot: {snapshot_id}")
    except Exception as e:
        print(f"Error deleting snapshot {snapshot_id}: {str(e)}")

==============================================================

The line: try: must be followed by an indented block of code (like dest_rds.delete_db_snapshot(...)). If there’s nothing inside or indentation is off, Python throws: SyntaxError: expected an indented block after 'try' statement

Pro Tip: Always use 4 spaces per indentation level (not tabs). Avoid pasting code directly into AWS Lambda console if it auto-indents unpredictably.

answered 9 months ago
  • Hi Manvitha! Thank you for your help! I didn't not find in my python research the past few days that "indent" means (4) spaces and not simply hitting the "tab" key!
    "Always use 4 spaces per indentation level (not tabs). Avoid pasting code directly into AWS Lambda console if it auto-indents unpredictably." Very good to know, thanks again!

0

Hello.

I answered the question at the URL below, but I fixed the indentation throughout the code to eliminate any indentation-related errors.
https://repost.aws/questions/QUyMDhAVNeT52jVO68wGgdfA/made-suggested-indents-but-right-back-at-same-error-message#ANTQOlOs0pQD2kOA7zumPanw

import boto3
import os
from datetime import datetime

# Define regions
# SOURCE_REGION = "us-west-1"  # N. California
SOURCE_REGION = "us-west-2"  # Oregon
DEST_REGION = "us-west-2"    # Oregon
NUM_SNAPSHOTS = 2            # Number of snapshots to process

def lambda_handler(event, context):
# Create RDS clients for both regions
    source_rds = boto3.client('rds', region_name=SOURCE_REGION)
    dest_rds = boto3.client('rds', region_name=DEST_REGION)

# Step 1: Delete oldest manual snapshots in destination region
    delete_oldest_snapshots(dest_rds, NUM_SNAPSHOTS)

# Step 2: Copy latest system snapshots from source to destination
    copy_latest_snapshots(source_rds, dest_rds, NUM_SNAPSHOTS)

    return {
        'statusCode': 200,
        'body': f'Successfully processed {NUM_SNAPSHOTS} snapshots'
    }

def delete_oldest_snapshots(dest_rds, count):
# Get all manual snapshots in destination region
    response = dest_rds.describe_db_snapshots(SnapshotType='manual')

# Sort snapshots by creation time (oldest first)
    snapshots = sorted(response['DBSnapshots'], key=lambda s: s['SnapshotCreateTime'])

# Delete the oldest 'count' snapshots
    for i, snapshot in enumerate(snapshots):
        if i >= count:
            break

        snapshot_id = snapshot['DBSnapshotIdentifier']
        print(f"Deleting snapshot: {snapshot_id}")

        try:
            dest_rds.delete_db_snapshot(DBSnapshotIdentifier=snapshot_id)
            print(f"Successfully deleted snapshot: {snapshot_id}")
        except Exception as e:
            print(f"Error deleting snapshot {snapshot_id}: {str(e)}")

def copy_latest_snapshots(source_rds, dest_rds, count):
# Get all automated snapshots in source region
    response = source_rds.describe_db_snapshots(SnapshotType='automated')

    # Sort snapshots by creation time (newest first)
    snapshots = sorted(response['DBSnapshots'], 
        key=lambda s: s['SnapshotCreateTime'], 
        reverse=True
    )

    # Get today's date for naming
    today = datetime.now().strftime("%Y-%m-%d")

    # Define the database names based on your example
    #  "amgen", "alpine"
    db_names = [
        "demo", "drtest20240314"
    ]

    # Copy the newest 'count' snapshots
    for i, snapshot in enumerate(snapshots[:count]):
        if i >= count:
            break

        source_snapshot_id = snapshot['DBSnapshotIdentifier']
        db_instance_id = snapshot['DBInstanceIdentifier']

        # Use the corresponding db name from the list if available
        db_name = db_names[i] if i < len(db_names) else db_instance_id

        # Create target snapshot name
        target_snapshot_id = f"copy-rds-db-{db_name}-{today}"

        print(f"Copying snapshot {source_snapshot_id} to {target_snapshot_id}")

        try:
        # Create ARN for source snapshot
            source_arn = snapshot['DBSnapshotArn']

        # Copy the snapshot
            dest_rds.copy_db_snapshot(
                SourceDBSnapshotIdentifier=source_arn,
                TargetDBSnapshotIdentifier=target_snapshot_id,
                SourceRegion=SOURCE_REGION
            )
            print(f"Successfully initiated copy of {source_snapshot_id} to {target_snapshot_id}")
        except Exception as e:
            print(f"Error copying snapshot {source_snapshot_id}: {str(e)}")
EXPERT
answered 9 months ago
  • I upvoted and accepted your reply/answer on the other thread, "Made suggested indents but right back at same error message" but wanted to thank you here as well! I've repasted my reply/comment here below for others reading this to have good understanding: Thank you again - Donald

    Riku - I want to thank you very much for helping me out! I did not realize that "tab" does not create the appropriate indent action, which I was doing. The re-format you provided worked like a charm and the test ran until it a timeout error (Sandbox.Timedout), which I believe I can fix via re-configuring the timeout setting. For others reading this, the timeout error is: Status: Failed Test Event Name: TestEventLambdaSnap2

    Response: { "errorType": "Sandbox.Timedout", Thank you again Riku! Best Regards, Donald

-1

The error "name 'snapshot' is not defined" is occurring because your indentation in the delete_oldest_snapshots function is incorrect. The line snapshot_id = snapshot['DBSnapshotIdentifier'] and the code below it are not properly indented within the for loop.

In Python, indentation defines code blocks, so when your indentation is incorrect, Python treats the code as being outside of the loop where the snapshot variable is defined. This causes the error because snapshot is only defined within the scope of the for loop.

To fix this issue, you need to properly indent the code inside the for loop in the delete_oldest_snapshots function. Here's how the corrected function should look:

def delete_oldest_snapshots(dest_rds, count):
# Get all manual snapshots in destination region
response = dest_rds.describe_db_snapshots(SnapshotType='manual')

# Sort snapshots by creation time (oldest first)
snapshots = sorted(response['DBSnapshots'], key=lambda s: s['SnapshotCreateTime'])

# Delete the oldest 'count' snapshots
for i, snapshot in enumerate(snapshots):
if i >= count:
break

snapshot_id = snapshot['DBSnapshotIdentifier']
print(f"Deleting snapshot: {snapshot_id}")

try:
dest_rds.delete_db_snapshot(DBSnapshotIdentifier=snapshot_id)
print(f"Successfully deleted snapshot: {snapshot_id}")
except Exception as e:
print(f"Error deleting snapshot {snapshot_id}: {str(e)}")

Notice that all the code that uses the snapshot variable is indented to be inside the for loop. This ensures that snapshot is defined when you try to access it.

The same indentation issue appears to exist in your copy_latest_snapshots function as well, so you'll need to fix the indentation there too.
Sources
Troubleshooting cluster deployment issues - AWS ParallelCluster

answered 9 months ago
  • Regarding, "Here's how the corrected function should look" But there are no indentations in the code example below that statement in the reply.

  • I put the code exactly like the, "To fix this issue, you need to properly indent the code inside the for loop in the delete_oldest_snapshots function. Here's how the corrected function should look:"

    And I get an indented block error: { "errorMessage": "Syntax error in module 'lambda_function': expected an indented block after function definition on line 27 (lambda_function.py, line 29)", "errorType": "Runtime.UserCodeSyntaxError", "requestId": "", "stackTrace": [ " File "/var/task/lambda_function.py" Line 29\n response = dest_rds.describe_db_snapshots(SnapshotType='manual')\n" ] }

  • Added indentation and fixed that line. But now it's asking for another indentation, I bet after I re-indent every line it asks to fix I will be back to the original error of the is post, ie : "Error: "errorMessage": "name 'snapshot' is not defined","

    Response: { "errorMessage": "Syntax error in module 'lambda_function': expected an indented block after 'try' statement on line 42 (lambda_function.py, line 43)", "errorType": "Runtime.UserCodeSyntaxError", "requestId": "", "stackTrace": [ " File "/var/task/lambda_function.py" Line 43\n dest_rds.delete_db_snapshot(DBSnapshotIdentifier=snapshot_id)\n" ] }

  • Yup. Made the indents and I'm right back to my original error: "errorMessage": "name 'snapshot' is not defined",

    The suggestions above did not help.

  • Can a human have a look please ?

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.