【问题标题】:Process CSV line by line from S3 using python on Lambda在 Lambda 上使用 python 从 S3 逐行处理 CSV
【发布时间】:2019-05-04 23:52:34
【问题描述】:

我正在尝试使用 AWS Lambda (Python) 处理 S3 存储桶上的 .csv (30MB) 文件。我在本地编写了 python 代码来处理文件,现在尝试使用 Lambda 执行。很难逐行读取文件。

请告诉我如何使用 boto3 或 s3 方法逐行遍历文件。请尽快帮助我。谢谢

在 Lambda 中:

s3 = boto3.client("s3")
        file_obj = event["Records"][0]
        filename=str(file_obj['s3']['object']['key'])
        #print('file name is :', filename)
        fileObj = s3.get_object(Bucket=<mybucket>, Key=filename)
        file_content = fileObj["Body"].read().decode('utf-8')

我的原始代码:

import csv
import pandas as pd
import datetime
#from datetime import datetime,timedelta
import numpy as np
with open ('sample.csv', 'r') as file_name:

    csv_reader = csv.reader(file_name, delimiter=',')
    Time = []
    Latitude=[]
    Longitude= []
    Org_Units=[]
    Org_Unit_Type =[]
    Variable_Name=[]
    #New columns
    Year=[]
    Month= []
    Day =[]
    Celsius=[]
    Far=[]
    Conv_Units=[]
    Conv_Unit_Type=[]
    header = ['Time','Latitude', 'Longitude','Org_Units','Org_Unit_Type','Conv_Units','Conv_Unit_Type','Variable_Name']
    out_filename = 'Write' + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") #need to rename based on the org file name

    with open(out_filename +'.csv', 'w') as csvFile:
        outputwriter = csv.writer(csvFile, delimiter=',')
        outputwriter.writerow(header)
        next(csv_reader, None)  # avoid hearder

        for row in csv_reader:
           # print(row)
            Time = row[0]
            Org_Lat=row[1]
            Org_Long=row[2]
            Org_Units=row[3]
            Org_Unit_Type =row[4]
            Variable_Name=row[5]
            # print(Time,Org_Lat,Org_Long,Org_Units,Org_Unit_Type,Variable_Name)

            if Org_Unit_Type == 'm s-1':
                Conv_Units =round(float(Org_Units) * 1.151,2)
                Conv_Unit_Type = 'miles'
            if Org_Unit_Type == 'm':
                Conv_Units =round(float(Org_Units) / 1609.344,2)
                 # print (Org_Units,Conv_Units)
                Conv_Unit_Type = 'miles'
            if Org_Unit_Type == 'Pa':
                Conv_Units =round(float(Org_Units) / 6894.757,2)
                Conv_Unit_Type = 'Psi'
                #print(type(Time))
            date_time_obj = datetime.datetime.strptime(Time, '%m-%d-%Y, %H:%M')
             #  Year = time.strptime(date_time_obj, "%B")
            #print(date_time_obj)
            f_row =[Time,Latitude,Longitude,Org_Units,Org_Unit_Type,Conv_Units,Conv_Unit_Type,Variable_Name]
            outputwriter.writerow(f_row)
csvFile.close()
print("done")

【问题讨论】:

  • 您好,您能否详细解释一下您的代码存在什么问题,即您遇到了什么错误,并提供一个可重现的最小示例?

标签: amazon-s3 aws-lambda


【解决方案1】:

我认为这应该有效,您唯一需要检查的是您的 lambda 需要一个角色,该角色具有对 s3 存储桶具有读取访问权限的策略。 最初为了测试,我会在 s3 上完全访问 lambda AmazonS3FullAccess

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "*"
        }
    ]
}

python 代码

s3 = boto3.client('s3')
def lambda_handler(event, context):
    # Get the object from the event and show its content type
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = event['Records'][0]['s3']['object']['key'].encode('utf8')
    obj = s3.get_object(Bucket=bucket, Key=key)
    rows    = obj['Body'].read().split('\n')
    print("rows" + rows)

【讨论】:

  • 我现在可以获取数据了,我的问题仍然是关于如何遍历并选择每一行和每一列的问题。对于 python 中的 ex,我正在做:对于 csv_reader 中的行:# print(row) Time = row[0] Org_Lat=row[1] Org_Long=row[2] 我当前的 Lambda 代码如下所示:
  • import boto3 def lambda_handler(event,context): s3 = boto3.client('s3') if event: #print("Evnet is:", event) file_obj =event['Records'] [0] filename = str(file_obj['s3']['object']['key']) print ('file is ---',filename) fileobj = s3.get_object(Bucket='我的桶名', key=filename) print('文件对象是--',fileobj) file_content =fileobj['Body'].read().decode('utf-8') header = ['Time','Latitude',跨度>
  • 'Longitude','Org_Units','Org_Unit_Type','Conv_Units','Conv_Unit_Type','Variable_Name'] 对于 file_content 中的行: print(row ) 请让我知道如何通过每行并为我的计算选择属性值。谢谢。
【解决方案2】:

与使用.read() 将对象作为流读取相比,您可能会发现将对象下载到本地存储更容易:

s3_client = boto3.client('s3', region='ap-southeast-2')
s3_client.download_file(bucket, key, '/tmp/local_file.csv')

然后您可以使用您的原始程序来处理该文件。

完成后,请务必删除临时文件,因为 AWS Lambda 容器可能会被重复使用,并且只有 500MB 可用磁盘空间。

【讨论】:

  • 嗨,约翰,文件大小约为 30-40MB。
  • 嗨,John,我可以使用 lambda 处理的最大数据文件大小是多少?
  • AWS Lambda 在/tmp/ 中提供了 500MB 的存储空间。单个文件大小限制将基于 Linux,这会比这大得多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-18
  • 1970-01-01
  • 1970-01-01
  • 2019-10-17
  • 2021-04-05
  • 2013-08-17
  • 1970-01-01
相关资源
最近更新 更多