Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在AWS S3中新文件到达时触发AWS Lambda_Python_Amazon Web Services_Amazon S3_Aws Lambda_Amazon Cloudwatch - Fatal编程技术网

Python 在AWS S3中新文件到达时触发AWS Lambda

Python 在AWS S3中新文件到达时触发AWS Lambda,python,amazon-web-services,amazon-s3,aws-lambda,amazon-cloudwatch,Python,Amazon Web Services,Amazon S3,Aws Lambda,Amazon Cloudwatch,我有一个用Python编写的Lambda函数,它的代码可以从AWS S3中的3个文件中为3个表运行红移复制命令 例如: if (new csv file for A has arrived): 'copy to redshift A from "s3://bucket/abc/A.csv"' if (new csv file for B has arrived): 'copy to redshift B from "s3://bucket/abc/B.csv"' if (new

我有一个用Python编写的Lambda函数,它的代码可以从AWS S3中的3个文件中为3个表运行红移复制命令

例如:

if (new csv file for A has arrived):
    'copy to redshift A from "s3://bucket/abc/A.csv"'
if (new csv file for B has arrived):
    'copy to redshift B from "s3://bucket/abc/B.csv"'
if (new csv file for C has arrived):
    'copy to redshift C from "s3://bucket/abc/C.csv"'
我有A、B和C桌

The python code contains:

'copy to redshift A from "s3://bucket/abc/A.csv"'
'copy to redshift B from "s3://bucket/abc/B.csv"'
'copy to redshift C from "s3://bucket/abc/C.csv"'
每当三个文件中的新文件到达s3中的“s3://bucket/abc/”位置时,就会触发此代码。因此,即使只有一个csv文件到达,它也会加载所有三个表

最佳解决方案:将代码分解为三个不同的Lambda函数,并直接将它们映射到每个源文件更新/上载

但是,我的要求是继续使用一个Lambda代码,它将有选择地运行它的一部分(使用if),仅用于更新的csv文件

例如:

if (new csv file for A has arrived):
    'copy to redshift A from "s3://bucket/abc/A.csv"'
if (new csv file for B has arrived):
    'copy to redshift B from "s3://bucket/abc/B.csv"'
if (new csv file for C has arrived):
    'copy to redshift C from "s3://bucket/abc/C.csv"'
目前,为了实现这一点,我将这些文件的元数据(LastModified)存储在python dict中,文件名是关键。打印dict应该是这样的:

{'bucket/abc/A.csv': '2019-04-17 11:14:11+00:00', 'bucket/abc/B.csv': '2019-04-18 12:55:47+00:00', 'bucket/abc/C.csv': '2019-04-17 11:09:55+00:00'}
然后,每当一个新文件出现在这三个文件中的任何一个文件中时,Lambda就会被触发,我会读取dict并将每个文件的时间和dict中的相应值进行比较,若新的LastModified增加,我会运行该表的copy命令

所有这些,因为对于这种用例,我找不到S3event/CloudWatch可以解决的问题


如果无法很好地阐明问题,请提出进一步的问题。

当Amazon S3事件触发AWS Lambda函数时,它将提供Bucket名称和对象键作为
事件的一部分

def lambda_handler(event, context):

  # Get the bucket and object key from the Event
  bucket = event['Records'][0]['s3']['bucket']['name']
  key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'])
虽然对象详细信息以列表形式传递,但我怀疑每个事件只提供了一个对象(因此使用了
[0]
)。然而,我不能100%肯定这种情况是否会一直持续下去。最好假设它,直到证明不是这样

因此,如果您的代码需要特定对象,那么您的代码应该是:

if key == 'abc/A.csv':
    'copy to Table-A from "s3://bucket/abc/A.csv"'
if key == 'abc/B.csv':
    'copy to Table-B from "s3://bucket/abc/B.csv"'
if key == 'abc/C.csv':
    'copy to Table-C from "s3://bucket/abc/C.csv"'
无需存储
LastModified
,因为每次上载新文件时都会触发该事件。另外,在将数据存储在全局dict中时要小心,并期望它在将来的执行中出现—情况并非总是如此。如果Lambda容器在一段时间内未运行,则可以删除它,如果存在并发执行,则可能会创建其他Lambda容器


如果您总是知道您需要3个文件,并且它们总是按特定顺序上传,那么您可以使用第3个文件的上传来触发该过程,然后将所有3个文件复制到Redshift。

@John Rotenstein不会通知John read。我在另一次对话中与他共享了该链接。我想那会有帮助的。谢谢成功了。谢谢现在,我实际上是以JSON blob的形式将值传递给Lambda代码,该代码由表细节、数据库、每个表的列等组成。但是如果触发器传递来自该源的数据,它将覆盖我通过测试事件部分传递的“事件”数据。我应该如何处理这个问题?提供测试事件功能来模拟触发Lambda函数时通常出现的数据。测试事件中的数据仅在测试功能时使用。当Lambda函数正常触发时,它将不存在。@JohnRotenstein如果我们将文件元数据保存在SQS中而不是触发Lambda,然后触发Lambda处理一批文件,而不是为每个添加的新文件触发Lambda,该怎么办。@ETL_Devs请创建一个新问题,而不是通过对旧问题的评论提问。