0

This question has two parts I guess but I will explain: The scenario:

I have a lambda function that creates a folder in S3 for a user if they don't have one, and then it will eventually be populated with mp3 files. For my test cases, I have to handle for if the file exists. For that, I am trying to use this:

s3client = boto3.client('s3')
bucket_name = os.environ['BUCKET_NAME']
prefix = email + "/"
resp = s3client.list_objects(Bucket=bucket_name, Prefix=prefix, Delimiter="/")
print resp 
print resp.get(email + "/" + postId + ".mp3")

I always get NoneType because it doesn't exist, but for testing purposes I have everything created already and I just want the success case to go through, so it does exist but I am not properly 'getting' the info.

The response I get from printing the 'resp' variable is:

{u'Name': 'listen-n-save-mp3', 'ResponseMetadata': {'HTTPStatusCode': 200, 'RetryAttempts': 0, 'HostId': 'QcxxxfYu1GunfZ2dXMUo=', 'RequestId': '16BCFFD288F16D74', 'HTTPHeaders': {'x-amz-bucket-region': 'us-east-1', 'x-amz-id-2': 'QRxZVUnWzcxxx22K5RoFKgxKfYu1GunfZ2dXMUo=', 'server': 'AmazonS3', 'transfer-encoding': 'chunked', 'x-amz-request-id': '16BCFFD288F16D74', 'date': 'Tue, 16 Oct 2018 19:23:06 GMT', 'content-type': 'application/xml'}}, u'Delimiter': u'/', u'MaxKeys': 1000, u'Prefix': 'philips%40exmaple.com/', u'Marker': u'', u'EncodingType': 'url', u'IsTruncated': False, u'Contents': [{u'LastModified': datetime.datetime(2018, 10, 16, 19, 22, 6, tzinfo=tzlocal()), u'ETag': '"xxxx"', u'StorageClass': 'STANDARD', u'Key': u'philips@exmaple.com/', u'Owner': {u'DisplayName': 'listennsave', u'ID': 'xxxx'}, u'Size': 0}, {u'LastModified': datetime.datetime(2018, 10, 16, 18, 57, 43, tzinfo=tzlocal()), u'ETag': '"xxxx"', u'StorageClass': 'STANDARD', u'Key': u'philips@exmaple.com/supImanId.mp3', u'Owner': {u'DisplayName': 'listennsave', u'ID': 'xxx'}, u'Size': 36942}]}

The response is really long and formatted to one line automatically unfortunately, but there is a key inside the folder called u'Key': u'philips@exmaple.com/supImanId.mp3' that you can see toward the end of that one-liner. My first question is how can I access that key properly with my get method?

My second question is, when I know I am getting the key properly and it returns NoneType (meaning it hasnt been created yet) how could I use that as a conditional statement that allows the function to continue?

Thanks for your time.

=================================================================

Edit: This is what I have right now

s3client = boto3.client('s3')
bucket_name = os.environ['BUCKET_NAME']
prefix = email + "/"
print bucket_name
resp = s3client.list_objects(Bucket=bucket_name, Prefix=prefix, Delimiter="/")

this_item =  [item for item in resp['Contents'] if item.get('Key')==email + "/" + postId + ".mp3" ]
try:
    this_item[0]['Key']
except IndexError:
    pass
continue

The problem is, if I get returned nothing I want this function to work properly. I tried with this syntax but I receive an error about looping

Syntax error in module 'lambda_function': 'continue' not properly in loop (lambda_function.py, line 80)

So I need a loop I assume? Where and how should I start the loop with my current set up? Seems simple but I am very new to Python so it would be helpful!

Philip Morgan
  • 33
  • 2
  • 7

1 Answers1

0

The response from list_objects() follows a defined structure that defines a bunch of metadata about the request along with the result contents. You can read more about the specifics of what is in the response file and how it is structured in the boto3 documentation.

The response object is just a dictionary. The value for Key is nested within Contents, so to access Key in the response object you can use:

k = resp['Contents']['Key']

If multiple keys are returned by the request then you could alternatively just loop through the Contents objects and create a list of all the keys return like this:

all_keys = [k["Key"] for k in resp["Contents"]
vielkind
  • 2,840
  • 1
  • 16
  • 16
  • I appreciate the response, I thought about the problem and I realized it is pretty simple even if I do not know Python. I have a similar answer to yours in my edit but I need to handle for NoneType properly. I was wondering how I could set that loop up in my scenario. Sorry if I am asking a bad question but I felt I needed to talk through the issue with someone. I will check your answer anyway. – Philip Morgan Oct 17 '18 at 19:09
  • Your question isn't entirely clear. If you're just looking to determine if a key exists you should checkout this answer: [Check if a Key Exists in a S3 Bucket](https://stackoverflow.com/questions/33842944/check-if-a-key-exists-in-a-bucket-in-s3-using-boto3). You don't need to use `list_objects()` and can test for the key directly then capture the instance where the key doesn't exist. Also note, `list_objects()` only returns 1000 items. If you have more than that being returned you'll run into issues. – vielkind Oct 17 '18 at 20:16