python - 如何从 S3 存储桶中读取 CSV 文件,对其应用某些 if 语句,然后编写新的更新 CSV 文件并将其放入 S3 存储桶中?
问题描述
我无法将新的 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)
我希望这行得通。基本上有几个技巧:
- 用于
codecs
直接从 s3 存储桶流式传输 csv 数据 - 用于
BytesIO
在内存中创建一个csv.DictWriter
可以写入的流。 - 完成后,“上传”内容的一种方法是通过
s3.clients
'sput_object
方法(如 AWS 中所述)
推荐阅读
- javascript - 使用 fetched API 创建多个元素
- java - 使用 docker-compose 运行我的应用程序时出现 java.security.KeyStoreException
- conditional-statements - 我是否可以为 Azure DevOps Server 构建步骤创建一个自定义条件,该条件将在一段时间内运行该步骤?
- python - 无法在 open3D 中对点云进行下采样
- bash - 无法以 root 身份运行脚本,但在没有它的情况下权限被拒绝
- reactjs - react-chartjs-2 刻度不会与中心对齐
- flutter - 无法将文件保存到我的设备android10颤动
- c# - 如何从 UIElement 中删除父级?WPF
- mongodb - MongooseError:操作 `dbs.findOne()` 缓冲在 10000 毫秒后超时
- sql - INNER JOIN 多个列到另一个表的同一列