Python 如何从S3存储桶中读取CSV文件、对其应用某些if语句、编写新的更新CSV文件并将其放入S3存储桶中?

Python 如何从S3存储桶中读取CSV文件、对其应用某些if语句、编写新的更新CSV文件并将其放入S3存储桶中?,python,amazon-web-services,csv,amazon-s3,aws-lambda,Python,Amazon Web Services,Csv,Amazon S3,Aws Lambda,我无法将新CSV文件写入S3存储桶。我希望能够读取S3存储桶中的CSV文件,如果CSV中的某个值符合特定要求,我希望将其更改为其他值。我读到不可能编辑S3对象,所以每次都需要创建一个新对象。简而言之,我想从S3存储桶中的另一个CSV文件创建一个新的、更新的CSV文件,并应用更改 我尝试使用DictWriter和DictReader,但我总是遇到DictWriter的问题。我可以正确地读取CSV文件,但当我尝试更新它时,与DictWriter有许多明显不同的问题。现在,我遇到的问题是 # Func

我无法将新CSV文件写入S3存储桶。我希望能够读取S3存储桶中的CSV文件,如果CSV中的某个值符合特定要求,我希望将其更改为其他值。我读到不可能编辑S3对象,所以每次都需要创建一个新对象。简而言之,我想从S3存储桶中的另一个CSV文件创建一个新的、更新的CSV文件,并应用更改

我尝试使用DictWriter和DictReader,但我总是遇到DictWriter的问题。我可以正确地读取CSV文件,但当我尝试更新它时,与DictWriter有许多明显不同的问题。现在,我遇到的问题是

# Function to be pasted into AWS Lambda.
# Accesses S3 bucket, opens the CSV file, receive the response line-by-line, 

# To be able to access S3 buckets and the objects within the bucket
import boto3

# To be able to read the CSV by using DictReader 
import csv

# Lambda script that extracts, transforms, and loads data from S3 bucket 'testing-bucket-1042' and CSV file 'Insurance.csv'

def lambda_handler(event, context):
    s3 = boto3.resource('s3')
    bucket = s3.Bucket('testing-bucket-1042')
    obj = bucket.Object(key = 'Insurance.csv')
    response = obj.get()
    lines = response['Body'].read().decode('utf-8').split()

    reader = csv.DictReader(lines) 

    with open("s3://testing-bucket-1042/Insurance.csv", newline = '') as csvfile:
            reader = csv.DictReader(csvfile)
            fieldnames = ['county', 'eq_site_limit'] 
            writer = csv.DictWriter(lines, fieldnames=fieldnames)

            for row in reader: 
                writer.writeheader()
                if row['county'] == "CLAY": # if the row is under the column 'county', and contains the string "CLAY"
                    writer.writerow({'county': 'CHANGED'})
                if row['eq_site_limit'] == "0": # if the row is under the column 'eq_site_limit', and contains the string "0"
                    writer.writerow({'eq_site_limit': '9000'})
现在,我得到的错误是,我在尝试打开CSV时使用的路径“s3://testing-bucket-1042/Insurance.CSV”据说不存在

错误是

“errorMessage:“[Errno 2]没有这样的文件或目录:'s3://testing-bucket-1042/Insurance.csv'”, “errorType”:“FileNotFoundError”


如果使用DictWriter,正确的方法是什么?

首先
s3:\\
不是常见的(文件)协议,因此您会收到错误消息。很好,你表明了你的意图

好的,我重构了你的代码

import codecs

import boto3

# To be able to read the CSV by using DictReader
import csv
from io import StringIO

# Lambda script that extracts, transforms, and loads data from S3 bucket 'testing-bucket-1042' and CSV file 'Insurance.csv'

def lambda_handler(event, context):
    s3 = boto3.resource('s3')
    bucket = s3.Bucket('testing-bucket-1042')
    obj = bucket.Object(key = 'Insurance.csv')
    stream = codecs.getreader('utf-8')(obj.get()['Body'])
    lines = list(csv.DictReader(stream))
    ### now you have your object there

    csv_buffer = StringIO()
    out = csv.DictWriter(csv_buffer, fieldnames=['county', 'eq_site_limit'])

    for row in lines:
        if row['county'] == "CLAY":  
            out.writerow({'county': 'CHANGED'})
        if row['eq_site_limit'] == "0": 
            out.writerow({'eq_site_limit': '9000'})

    ### now write content into some different bucket/key

    s3client = boto3.client('s3')
    s3client.put_object(Body=csv_buffer.getvalue().encode(encoding),
                        Bucket=...targetbucket, Key=...targetkey)
我希望这能奏效。基本上有几个技巧:

  • 使用
    编解码器
    直接从s3存储桶传输csv数据
  • 使用
    BytesIO
    在内存中创建
    csv.DictWriter
    可以写入的流
  • 完成后,“上传”内容的一种方法是通过
    s3。客户端的
    put\u对象
    方法(如AWS中所述)

要从逻辑上将AWS代码与业务逻辑分开,我通常建议采用以下方法:

  • 将对象从Amazon S3下载到
    /tmp
    目录
  • 执行所需的业务逻辑(读文件、写文件)
  • 将生成的文件上载到Amazon S3
使用
download_file()
upload_file()
可以避免担心内存流。这意味着您可以采用通常在文件上运行的逻辑(例如在您自己的计算机上),然后将其应用于从S3获取的文件


这取决于个人喜好。

您可以使用S3的流媒体功能随时进行更改。它更适合于文本操作工具,如
awk
sed

例如:

aws s3 cp s3://bucketname/file.csv - | sed 's/foo/bar/g' | aws s3 cp -  s3://bucketname/new-file.csv

AWS文档:

您可能应该使用boto3 API上传生成的CSV,但如果出于某种原因确实需要使用常规Python文件接口到S3,那么您可能需要查看一下。感谢您的快速响应!我仍然遇到out.writerow({'county':'CHANGED'})的问题。错误消息表示“需要类似字节的对象,而不是'str'”。你能帮我做这个吗?