Как узнать размер коллекции boto3?

Я использовал способ преобразования коллекции в список и запроса длины:

s3 = boto3.resource('s3')
bucket = s3.Bucket('my_bucket')
size = len(list(bucket.objects.all()))

Однако это приводит к разрешению всей коллекции и в первую очередь сводит на нет преимущества использования коллекции. Есть лучший способ сделать это?


person Rahul Gupta-Iwasaki    schedule 05.09.2015    source источник


Ответы (3)


Невозможно получить количество ключей в корзине без перечисления всех объектов, это ограничение AWS S3 (см. https://forums.aws.amazon.com/thread.jspa?messageID=164220).

Получение сводок объектов (HEAD) не дает фактических данных, поэтому это должна быть относительно недорогая операция, и если вы просто отбрасываете список, вы можете сделать:

size = sum(1 for _ in bucket.objects.all())

Что даст вам количество объектов без построения списка.

person AChampion    schedule 05.09.2015
comment
Если вас интересует определенный префикс ключа или папка, это было полезно size = sum(1 for _ in bucket.objects.filter(Prefix='my_key_prefix/')) - person cheevahagadog; 19.05.2020

Заимствование из похожий вопрос, один из вариантов получения полного списка ключей объектов из корзины + префикс — использовать рекурсию с list_objects_v2.

Этот метод будет рекурсивно извлекать список ключей объекта, по 1000 ключей за раз.

Каждый запрос к list_objects_v2 использует аргумент StartAfter для продолжения списка ключей после последнего ключа из предыдущего запроса.

import boto3

if __name__ == '__main__':

    client = boto3.client('s3',
        aws_access_key_id     = 'access_key',
        aws_secret_access_key = 'secret_key'
    )

    def get_all_object_keys(bucket, prefix, start_after = '', keys = []):
        response = client.list_objects_v2(
            Bucket     = bucket,
            Prefix     = prefix,
            StartAfter = start_after
        )

        if 'Contents' not in response:
            return keys

        key_list = response['Contents']
        last_key = key_list[-1]['Key']

        keys.extend(key_list)

        return get_all_object_keys(bucket, prefix, last_key, keys)

    object_keys = get_all_object_keys('your_bucket', 'prefix/to/files')

    print(len(object_keys))
person doremi    schedule 08.03.2017
comment
Использование интерфейса более высокого уровня Boto3 (например, коллекций) позволяет библиотеке выполнять все пейджинговые операции. Использование рекурсии и изменяемого аргумента по умолчанию кажется странным выбором в этом примере. Это также означает, что эту функцию нельзя вызывать дважды. - person AChampion; 14.10.2019

В моем случае мне просто нужно было знать, пуста ли папка или нет.

s3 = boto3.client('s3')
response = s3.list_objects(
        Bucket='your-bucket',
        Prefix='path/to/your/folder/',
)
print(len(response['Contents']))

Этого было достаточно, чтобы узнать, пуста ли папка. Обратите внимание, что папка, созданная вручную в консоли S3, сама по себе может считаться ресурсом. В этом случае, если указанная выше длина больше 1, то «папка» S3 пуста.

person andersan    schedule 21.05.2018
comment
Следует отметить, что list_objects возвращает максимум 1000 объектов. - person Richard; 20.02.2019
comment
Вы имеете в виду, что если указанная выше длина больше 1, то папка S3 НЕ пуста? - person Ronnie; 13.04.2020
comment
Эй, @Ронни, верно. Если длина больше 1, папка НЕ ​​пуста — сама папка возвращается как один из этих объектов. Может быть полезно проверять заголовок объектов, а не перечислять сам объект. Для моего варианта использования мне все равно нужно было получить объекты. - person andersan; 22.04.2020
comment
@andersan правильно, тогда иди и отредактируй свой ответ. - person Ronnie; 22.04.2020