Reputation: 3
Below is the code to trigger a lambda function when a csv file is uploaded to an Amazon S3 bucket and write data to an Amazon DynamoDB table. I am getting error "expected str, bytes or os.PathLike object, not dict".
Could you please suggest where is the mistake I did.
import boto3
import csv
s3_client = boto3.client('s3')
dynamodb = boto3.resource('dynamodb')
#table = dynamodb.Table('batch_data')
def csv_write(table_name, rows):
table = dynamodb.Table(table_name)
with table.csv_write() as batch:
for row in rows:
batch.put_item(Item=row)
return True
def read_csv(csv_file, list):
rows = csv.DictReader(open(csv_file))
for row in rows:
list.append(row)
def lambda_handler(event, context):
try:
bucket = event['Records'][0]['s3']['bucket']['name']
csv_file_name = event['Records'][0]['s3']['object']['key']
response = s3_client.get_object(Bucket=bucket, Key= csv_file_name)
table_name = 'batch_data'
items = []
read_csv(response, items)
status = csv_write(table_name, items)
if(status):
print('Data saved')
else:
print('Error in saving data...')
except Exception as err:
print (err)
```
Upvotes: 0
Views: 1396
Reputation: 270224
This line:
response = s3_client.get_object(Bucket=bucket, Key= csv_file_name)
returns an object like this:
{
'Body': StreamingBody(),
'LastModified': datetime(2015, 1, 1),
'ContentLength': 123,
...
}
This line:
read_csv(response, items)
is passing that response
to this function as csv_file
:
def read_csv(csv_file, list):
rows = csv.DictReader(open(csv_file))
...
However, the open()
command doesn't know how to interpret the response object from S3. That is why it is returning the error:
expected str, bytes or os.PathLike object, not dict
Based on information from How do I read a csv stored in S3 with csv.DictReader?, I got this code working:
import boto3
import csv
def lambda_handler(event, context):
s3_client = boto3.client('s3')
bucket = event['Records'][0]['s3']['bucket']['name']
csv_file_name = event['Records'][0]['s3']['object']['key']
response = s3_client.get_object(Bucket=bucket, Key= csv_file_name)
lines = response['Body'].read().decode('utf-8').split()
for row in csv.DictReader(lines):
print(row)
You can use that method to read the CSV from the StreamingBody
that is returned from get_object()
.
Upvotes: 1
Reputation: 804
likely your bucket or csv_file_name is inadvertently a dictionary, i.e. you didn't exhaust the hierarchy of event
Upvotes: 0