【问题标题】:AWS-Lambda: How to deal with SNS event in pythonAWS-Lambda:如何在 python 中处理 SNS 事件
【发布时间】:2020-06-14 07:03:47
【问题描述】:

如何从 SNS 事件中获取存储桶名称?

S3 存储桶将事件发布到 SNS 主题。本主题触发 Lambda。我需要 SNS,因为其他一些进程也监听这个事件。所以我不能直接从 S3 触发 Lambda。

在 lambda 函数中,我得到两个参数:eventcontext 我需要从事件中获取存储桶名称。我期待做这样的事情:

bucket = event['Records'][0]['s3']['bucket']['name']

但这不起作用,因为根据 Cloudwatch,事件参数如下所示:

{
    "Records":[
        {
            "EventSource":"aws:sns",
            "EventVersion":"1.0",
            "EventSubscriptionArn":"arn:aws:sns:eu-central-1:123456:sns-topic-dam-poc-new-import1:823baaf4-93b6-499a-944e-c99e1a6b1fb5",
            "Sns":{
                "Type":"Notification",
                "MessageId":"2330809c-29c4-5826-910d-d64a7ab22247",
                "TopicArn":"arn:aws:sns:eu-central-1:123456:sns-topic-dam-poc-new-import1",
                "Subject":"None",
                "Message":"{\\'Records\\': [{\\'EventSource\\': \\'aws:sns\\', \\'EventVersion\\': \\'1.0\\', \\'EventSubscriptionArn\\': \\'arn:aws:sns:eu-central-1:123456:sns-topic-dam-poc-new-import1:823baaf4-93b6-499a-944e-c99e1a6b1fb5\\', \\'Sns\\': {\\'Type\\': \\'Notification\\', \\'MessageId\\': \\'b611d3b2-a0d4-55fe-af0f-85648ffc2a59\\', \\'TopicArn\\': \\'arn:aws:sns:eu-central-1:123456:sns-topic-dam-poc-new-import1\\', \\'Subject\\': \\'None\\', \\'Message\\': \\'{\\n   \"Records\":[\\n      {\\n         \"EventSource\":\"aws:sns\",\\n         \"EventVersion\":\"1.0\",\\n         \"EventSubscriptionArn\":\"arn:aws:sns:eu-central-1:123456:sns-topic-dam-poc-new-import1:823baaf4-93b6-499a-944e-c99e1a6b1fb5\",\\n         \"Sns\":{\\n            \"Type\":\"Notification\",\\n            \"MessageId\":\"906fd69c-ee31-50f2-8b9d-804910f6fdcd\",\\n            \"TopicArn\":\"arn:aws:sns:eu-central-1:123456:sns-topic-dam-poc-new-import1\",\\n            \"Subject\":\"Amazon S3 Notification\",\\n            \"Message\":\"{\\\\\"Service\\\\\":\\\\\"Amazon S3\\\\\",\\\\\"Event\\\\\":\\\\\"s3:TestEvent\\\\\",\\\\\"Time\\\\\":\\\\\"2020-03-01T18:18:46.898Z\\\\\",\\\\\"Bucket\\\\\":\\\\\"s3-dam-poc-dev-inbox\\\\\",\\\\\"RequestId\\\\\":\\\\\"9534F72BD9216CA8\\\\\",\\\\\"HostId\\\\\":\\\\\"hSPdeBzns8wjrMHqkFJgw1UPMv0aZ/VOsAxw/z9wtboR+TOy8sKSKElDYxm9kszokgPsBU9T1nU=\\\\\"}\",\\n            \"Timestamp\":\"2020-03-01T18:18:47.036Z\",\\n            \"SignatureVersion\":\"1\",\\n            \"Signature\":\"FuoBKJczUXuKJ58d5SdddqnOjMwjxzG2aN+sef/0M5MFsAjRMyCNknvaXVVRrhujK39HouoOoDqyJNFzDWYR3WTYAM0Sqws9wJK9zBV9mxmMYdIurfDmVj4xsF4xuSeaMy4y/VfU2r75DxqhE3MPmA02IuGInGJsmw9CTk+Ao+kdnk/6rJT+Bt3EKK7uKj3kIWYehPDCYKYdzCsDcaP+Aaj2qEhEbkZxdaopB+pHRkMsLhZS/vHcc0Vd1eyZkRYHkxrG4FeKXVZdJT5OGuyixOSWq9YdCBJhWRnq7cRlQnk05WfswWdukOw9yjBkidsT1pJoiBQ==\",\\n            \"SigningCertUrl\":\"https://sns.eu-central-1.amazonaws.com/SimpleNotificationService-a86cb10b4e1f29c941702d7371d28f7b6.pem\",\\n            \"UnsubscribeUrl\":\"https://sns.eu-central-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-central-1:123456:sns-topic-dam-poc-new-import1:823baaf4-93b6-499a-944e-c99e1a6b1fb5\",\\n            \"MessageAttributes\":{\\n\\n            }\\n         }\\n      }\\n   ]\\n}\\', \\'Timestamp\\': \\'2020-03-01T21:45:12.192Z\\', \\'SignatureVersion\\': \\'1\\', \\'Signature\\': \\'pt7Mkfo+CB5rsHAnWWB7Kb/LtgBCZSJWc2fLTB84FhZ9/MFUK0pOYmou97dAgn1hdo48JEXnQKpnMN5flmxwGEmG6SPHklnSAgE18a0Bv0qQgzQ1KF9PIY2ulRJiebbuE0gToTlDCgiUGd0OJpZ5Cdr4TSZgOpT4AcDD4NcpGCBKMTRwTcllaQDTNWF2mko9y6iqLp08ptq14qm4ppu9hrdGUU3klxE77Psn+7El6Cv3R8/asdfasdfaksdjhfiqwezhfknabsdfiugasdkf33==\\', \\'SigningCertUrl\\': \\'https://sns.eu-central-1.amazonaws.com/SimpleNotificationService-ashk38dn298djhxo8he2lknfO.pem\\', \\'UnsubscribeUrl\\': \\'https://sns.eu-central-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-central-1:123456:sns-topic-dam-poc-new-import1:823baaf4-93b6-499a-944e-c99e1a6b1fb5\\', \\'MessageAttributes\\': {}}}]}",
                "Timestamp":"2020-03-02T00:20:06.458Z",
                "SignatureVersion":"1",
                "SigningCertUrl":"https://sns.eu-central-1.amazonaws.com/SimpleNotificationService-d3iiiffndoendii3mmmdi3.pem",
                "UnsubscribeUrl":"https://sns.eu-central-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-central-1:123456:sns-topic-dam-poc-new-import1:823baaf4-93b6-499a-944e-c99e1a6b1fb5",
                "MessageAttributes":{

                }
            }
        }
    ]
}

我可以在Message 中看到存储桶名称 这是我的python代码:

import boto3
def newImportHandler(event, context):
    print("__________")
    print(event)
    print("__________")
    simple1 = event['Records'][0]['Sns']['Message']
    print('Simple 1 '+simple1)
    simple2 = simple1['Records'][0]
    print('Simple 2 '+simple2)

simple1 是一个字符串!所以这段代码失败了!

【问题讨论】:

  • 尝试message = json.loads(event['Records'][0]['Sns']['Message']),然后访问message['Records'][0]
  • 我已经尝试过了,一旦我完成了 json 加载,变量 'message' 原来是一个字符串。所以 message['Records'] 失败,字符串索引必须是整数 ...
  • 我认为您必须再次运行json.loads,因为您已将消息嵌入到其他消息中。所以也需要json.loads内部消息。
  • 此消息格式错误。不幸的是 json.load 失败:“JSONDecodeError:期望用双引号括起来的属性名称:”
  • 你必须玩这个,我们有很多转义字符,例如` \"消息\":\"{\\\\\"服务\\\\\":\\\\\"`

标签: python amazon-web-services amazon-s3 aws-lambda amazon-sns


【解决方案1】:

为了重现您的情况,我做了以下操作:

  • 创建了一个 Amazon S3 存储桶
  • 创建了一个Amazon SNS 主题并修改了接受来自存储桶的请求的权限(取自Example Walkthrough: Configure a Bucket for Notifications
  • 创建了一个 AWS Lambda 函数并将其订阅到 SNS 主题
  • 在存储桶上配置了一个 Amazon S3 事件,以向 SNS 主题发送消息
  • 通过将文件上传到存储桶进行测试

Lambda 代码对我来说很好用:

import json

def lambda_handler(event, context):
    
    message = json.loads(event['Records'][0]['Sns']['Message'])
    bucket = message['Records'][0]['s3']['bucket']['name']
    key = message['Records'][0]['s3']['object']['key']
    ...

【讨论】:

  • 对于复制和粘贴此代码的其他人,请注意在行尾有尾随关闭括号来设置应删除的存储桶和密钥变量。这是一个很容易解决的问题,但我花了一秒钟来找出语法错误,希望这条评论能为您节省一分钟左右的时间。
  • 已修复,谢谢!顺便说一句,如果您有足够的声誉,请随时编辑答案以修复此类错误。
  • 我不知道我可以编辑其他人的答案。感谢您指出这一点!
【解决方案2】:

我也收到了一个错误,并且根据处理包含 SNS 消息的 lambda 事件的 AWS 文档,此代码应该是一个起点:

def lambda_handler(event, context):
    #print("Received event: " + json.dumps(event, indent=2))
    message = event['Records'][0]['Sns']['Message']
    print("From SNS: " + message)
    return message

但是,在我写这篇文章的时候,事件的实际格式需要像这样访问消息:

string_msg = event['Records'][0]['Sns']['Message']
sns_msg = json.loads(string_msg)

然后,对于 S3 事件数据:

s3_event_data = sns_msg['Records'][0]['s3']

事件字典中的实际“消息”条目仍然是字符串化的 JSON,需要加载才能获取实际的 S3 事件数据。

【讨论】:

    猜你喜欢
    • 2016-10-01
    • 2017-12-01
    • 1970-01-01
    • 2018-05-18
    • 1970-01-01
    • 2021-02-13
    • 2017-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多