How do I list directory contents of an S3 bucket using Python and Boto3?

I am trying to list all directories within an S3 bucket using Python and Boto3.

I am using the following code:

s3 = session.resource('s3')  # I already have a boto3 Session object
bucket_names = [
    'this/bucket/',
    'that/bucket/'
]
for name in bucket_names:
    bucket = s3.Bucket(name)
    for obj in bucket.objects.all():  # this raises an exception
        # handle obj

When I run this I get the following exception stack trace:

File "botolist.py", line 67, in <module>
  for obj in bucket.objects.all():
File "/Library/Python/2.7/site-packages/boto3/resources/collection.py", line 82, in __iter__
  for page in self.pages():
File "/Library/Python/2.7/site-packages/boto3/resources/collection.py", line 165, in pages
  for page in pages:
File "/Library/Python/2.7/site-packages/botocore/paginate.py", line 83, in __iter__
  response = self._make_request(current_kwargs)
File "/Library/Python/2.7/site-packages/botocore/paginate.py", line 155, in _make_request
  return self._method(**current_kwargs)
File "/Library/Python/2.7/site-packages/botocore/client.py", line 270, in _api_call
  return self._make_api_call(operation_name, kwargs)
File "/Library/Python/2.7/site-packages/botocore/client.py", line 335, in _make_api_call
  raise ClientError(parsed_response, operation_name)

botocore.exceptions.ClientError: An error occurred (NoSuchKey) when calling the ListObjects operation: The specified key does not exist.

What is the correct way to list directories inside a bucket?

Many thanks in advance...


ANSWERS:


Alternatively you may want to use boto3.client

Example

>>> import boto3 
>>> client = boto3.client('s3')
>>> client.list_objects(Bucket='MyBucket')

list_objects also supports other arguments that might be required to iterate though the result: Bucket, Delimiter, EncodingType, Marker, MaxKeys, Prefix


If you have the session, create a client and get the CommonPrefixes of the clients list_objects:

client = session.client('s3', 
                        # region_name='eu-west-1'
                        )

result = client.list_objects(Bucket='MyBucket', Delimiter='/')
for obj in result.get('CommonPrefixes'):
    #handle obj.get('Prefix')

There could be a lot of folders, and you might want to start in a subfolder, though. Something like this could handle that:

def folders(client, bucket, prefix=''):
    paginator = client.get_paginator('list_objects')
    for result in paginator.paginate(Bucket=bucket, Prefix=prefix, Delimiter='/'):
        for prefix in result.get('CommonPrefixes', []):
            yield prefix.get('Prefix')

gen_folders = folders(client, 'MyBucket')
list(gen_folders)

gen_subfolders = folders(client, 'MyBucket', prefix='MySubFolder/')
list(gen_subfolders)

I would have thought that you can not have a slash in a bucket name. You say you want to list all directories within a bucket, but your code attempts to list all contents (not necessarily directories) within a number of buckets. These buckets probably do not exist (because they have illegal names). So when you run

bucket = s3.Bucket(name)

bucket is probably null, and the subsequent list will fail.



 MORE:


 ? In AWS, how to create elastic ip with boto3 ? or more generaly with python?
 ? In AWS, how to create elastic ip with boto3 ? or more generaly with python?
 ? In AWS, how to create elastic ip with boto3 ? or more generaly with python?
 ? python - Mount EBS volume using boto3
 ? python - Mount EBS volume using boto3
 ? python - Mount EBS volume using boto3
 ? Attaching and mounting existing EBS volume to EC2 instance filesystem issue
 ? aws python sdk boto3 client route53domains get_domain_suggestions ClientError
 ? aws python sdk boto3 client route53domains get_domain_suggestions ClientError
 ? aws python sdk boto3 client route53domains get_domain_suggestions ClientError