Листинг содержимого ведра с boto3

198

Как я могу увидеть, что внутри ведра в S3 с boto3? (т.е. делать "ls")?

Делать следующее:

import boto3
s3 = boto3.resource('s3')
my_bucket = s3.Bucket('some/path/')

возвращает:

s3.Bucket(name='some/path/')

Как я вижу его содержимое?

Амелио Васкес-Рейна
источник

Ответы:

244

Один из способов просмотра содержимого:

for my_bucket_object in my_bucket.objects.all():
    print(my_bucket_object)
garnaat
источник
1
я могу получить ключи по определенному пути в ведре или с определенным разделителем, используя boto3 ??
Рахул КП
110
Вы должны быть в состоянии сказать, mybucket.objects.filter(Prefix='foo/bar')и он будет перечислять только объекты с этим префиксом. Вы также можете передать Delimiterпараметр.
Гарнаат
3
не работает с boto3 AttributeError: у объекта 'S3' нет атрибута 'objects'
Shek
2
@garnaat Ваш комментарий о том, что метод фильтра действительно помог мне (мой код оказался намного проще и быстрее) - спасибо!
Эдвард Диксон,
24
Я бы посоветовал не использовать objectв качестве имени переменной, поскольку она будет скрывать глобальный тип object.
oliland
100

Это похоже на 'ls', но оно не учитывает соглашение о префиксной папке и перечисляет объекты в корзине. Читатель может отфильтровать префиксы, которые являются частью имени ключа.

В Python 2:

from boto.s3.connection import S3Connection

conn = S3Connection() # assumes boto.cfg setup
bucket = conn.get_bucket('bucket_name')
for obj in bucket.get_all_keys():
    print(obj.key)

В Python 3:

from boto3 import client

conn = client('s3')  # again assumes boto.cfg setup, assume AWS S3
for key in conn.list_objects(Bucket='bucket_name')['Contents']:
    print(key['Key'])
cgseller
источник
39
Если вы также хотите использовать префикс, вы можете сделать это так:conn.list_objects(Bucket='bucket_name', Prefix='prefix_string')['Contents']
markonovak
14
Это только список первых 1000 ключей. Из строки документации: «Возвращает некоторые или все (до 1000) объектов в ведре». Кроме того, рекомендуется использовать list_objects_v2 вместо list_objects (хотя это также возвращает только первые 1000 ключей).
Бретт Видмайер
3
Это ограничение должно быть решено
v25
44

Я предполагаю, что вы настроили аутентификацию отдельно.

import boto3
s3 = boto3.resource('s3')

my_bucket = s3.Bucket('bucket_name')

for file in my_bucket.objects.all():
    print(file.key)
Тушар Нирас
источник
30

Если вы хотите передать ключи ACCESS и SECRET (что делать не следует, потому что это небезопасно):

from boto3.session import Session

ACCESS_KEY='your_access_key'
SECRET_KEY='your_secret_key'

session = Session(aws_access_key_id=ACCESS_KEY,
                  aws_secret_access_key=SECRET_KEY)
s3 = session.resource('s3')
your_bucket = s3.Bucket('your_bucket')

for s3_file in your_bucket.objects.all():
    print(s3_file.key)
Эрвин Альберто
источник
13
Это менее безопасно, чем наличие файла учетных данных в ~ / .aws / credentials. Хотя это верное решение.
Ню Эверест
6
Это потребовало бы передачи секретов в систему контроля версий. Не хорошо.
Ян Грот
2
В этом ответе ничего не говорится об API / механике перечисления объектов при добавлении несоответствующего метода аутентификации, который является общим для всех ресурсов boto и является плохой практикой в
плане
Добавлен отказ от ответственности в ответ о безопасности.
Рюрни
Что, если ключи были предоставлены системой управления ключами / секретами, такой как Vault (Hashicorp) - разве это не было бы лучше, чем просто разместить файл учетных данных в ~ / .aws / credentials?
SunnyAk
26

Чтобы обрабатывать большие списки ключей (например, когда список каталогов превышает 1000 элементов), я использовал следующий код для накопления значений ключей (т.е. имен файлов) с несколькими списками (спасибо Амелио выше за первые строки). Код для python3:

    from boto3  import client
    bucket_name = "my_bucket"
    prefix      = "my_key/sub_key/lots_o_files"

    s3_conn   = client('s3')  # type: BaseClient  ## again assumes boto.cfg setup, assume AWS S3
    s3_result =  s3_conn.list_objects_v2(Bucket=bucket_name, Prefix=prefix, Delimiter = "/")

    if 'Contents' not in s3_result:
        #print(s3_result)
        return []

    file_list = []
    for key in s3_result['Contents']:
        file_list.append(key['Key'])
    print(f"List count = {len(file_list)}")

    while s3_result['IsTruncated']:
        continuation_key = s3_result['NextContinuationToken']
        s3_result = s3_conn.list_objects_v2(Bucket=bucket_name, Prefix=prefix, Delimiter="/", ContinuationToken=continuation_key)
        for key in s3_result['Contents']:
            file_list.append(key['Key'])
        print(f"List count = {len(file_list)}")
    return file_list
Гефест
источник
20

Моя служебная функция s3keys по сути является оптимизированной версией ответа @ Hephaestus:

import boto3


s3_paginator = boto3.client('s3').get_paginator('list_objects_v2')


def keys(bucket_name, prefix='/', delimiter='/', start_after=''):
    prefix = prefix[1:] if prefix.startswith(delimiter) else prefix
    start_after = (start_after or prefix) if prefix.endswith(delimiter) else start_after
    for page in s3_paginator.paginate(Bucket=bucket_name, Prefix=prefix, StartAfter=start_after):
        for content in page.get('Contents', ()):
            yield content['Key']

В моих тестах (boto3 1.9.84) это значительно быстрее, чем эквивалентный (но более простой) код:

import boto3


def keys(bucket_name, prefix='/', delimiter='/'):
    prefix = prefix[1:] if prefix.startswith(delimiter) else prefix
    bucket = boto3.resource('s3').Bucket(bucket_name)
    return (_.key for _ in bucket.objects.filter(Prefix=prefix))

Поскольку S3 гарантирует результаты в двоичном формате UTF-8 , start_afterоптимизация была добавлена ​​к первой функции.

Шон Саммерс
источник
Это, безусловно, лучший ответ. Я просто изменял ответ @ Гефеста (потому что он был самым высоким), когда прокручивал вниз. Это должен быть принятый ответ и получить дополнительные баллы за краткость. Я хотел бы добавить, что генератор из второго кода должен быть упакован, list()чтобы вернуть список файлов.
Ричард Д
@RichardD оба результата возвращают генераторы. Многие сегменты, которые я нацеливаю с этим кодом, имеют больше ключей, чем может обработать память исполнителя кода (например, AWS Lambda); Я предпочитаю использовать ключи по мере их создания.
Шон Саммерс
6

Более экономным способом, вместо того, чтобы перебирать цикл for, вы также можете просто напечатать исходный объект, содержащий все файлы внутри вашей корзины S3:

session = Session(aws_access_key_id=aws_access_key_id,aws_secret_access_key=aws_secret_access_key)
s3 = session.resource('s3')
bucket = s3.Bucket('bucket_name')

files_in_s3 = bucket.objects.all() 
#you can print this iterable with print(list(files_in_s3))
Даниэль Виейра
источник
3
@petezurich, не могли бы вы объяснить, почему такая мелкая правка моего ответа - замена «а» на заглавную «А» в начале моего ответа привела к снижению моей репутации на -2, однако я считаю, что и вы, и я могу согласиться это не только ваша коррекция НЕ имеет значения вообще, но на самом деле довольно мелкая, не так ли? Пожалуйста, сосредоточьтесь на содержании, а не на детском пересмотре, самый обязательный ol'boy
Даниэль Виейра
Это были два разных взаимодействия. 1. Я отредактировал ваш ответ, который рекомендуется даже для незначительных опечаток. Я согласен, что границы между незначительным и тривиальным неоднозначны. Я не понижаю ни одно сообщение, потому что я вижу ошибки, и я не сделал в этом случае. Я просто исправляю все ошибки, которые вижу.
petezurich
2. Я отклонил ваш ответ, потому что вы написали, что files_in_s3это «объект списка». В Python такого нет. Скорее, это итеративный код, и я не смог заставить ваш код работать, и поэтому я отказался Тогда я обнаружил ошибку и понял вашу точку зрения, но не смог отменить мое понижение.
petezurich
5
@petezurich нет проблем, понял вашу точку зрения, только одна вещь, в Python список - это объект, потому что почти все в python - это объект, тогда из этого также следует, что список также является итеративным, но, в первую очередь, это объект! Вот почему я не понял вашего отрицательного голоса - вы не голосовали за то, что было правильно, и за код, который работает. В любом случае, спасибо за ваши извинения и всего наилучшего
Даниэль Виейра
1
@petezurich Все в Python является объектом. «Список объектов» полностью приемлем.
Зак Гарвуд
4

ObjectSummary:

Есть два идентификатора, которые прикреплены к ObjectSummary:

  • bucket_name
  • ключ

boto3 S3: ObjectSummary

Подробнее об объектных ключах из документации AWS S3:

Ключи объекта:

Когда вы создаете объект, вы указываете имя ключа, которое однозначно идентифицирует объект в корзине. Например, в консоли Amazon S3 (см. Консоль управления AWS) при выделении сегмента отображается список объектов в нем. Эти имена являются ключами объекта. Имя для ключа представляет собой последовательность символов Unicode, кодировка UTF-8 которых имеет длину не более 1024 байтов.

Модель данных Amazon S3 представляет собой плоскую структуру: вы создаете контейнер, а контейнер хранит объекты. Нет иерархии вложенных или вложенных папок; однако вы можете вывести логическую иерархию, используя префиксы и разделители имен ключей, как это делает консоль Amazon S3. Консоль Amazon S3 поддерживает концепцию папок. Предположим, что ваше ведро (созданное администратором) имеет четыре объекта со следующими объектными ключами:

Разработка / Projects1.xls

Финансы / statement1.pdf

Частные лица / taxdocument.pdf

s3-dg.pdf

Ссылка:

AWS S3: ключи объекта

Вот пример кода, который демонстрирует, как получить имя корзины и ключ объекта.

Пример:

import boto3
from pprint import pprint

def main():

    def enumerate_s3():
        s3 = boto3.resource('s3')
        for bucket in s3.buckets.all():
             print("Name: {}".format(bucket.name))
             print("Creation Date: {}".format(bucket.creation_date))
             for object in bucket.objects.all():
                 print("Object: {}".format(object))
                 print("Object bucket_name: {}".format(object.bucket_name))
                 print("Object key: {}".format(object.key))

    enumerate_s3()


if __name__ == '__main__':
    main()
Gothburz
источник
3

Я просто сделал это так, включая метод аутентификации:

s3_client = boto3.client(
                's3',
                aws_access_key_id='access_key',
                aws_secret_access_key='access_key_secret',
                config=boto3.session.Config(signature_version='s3v4'),
                region_name='region'
            )

response = s3_client.list_objects(Bucket='bucket_name', Prefix=key)
if ('Contents' in response):
    # Object / key exists!
    return True
else:
    # Object / key DOES NOT exist!
    return False
Milean
источник
2
#To print all filenames in a bucket
import boto3

s3 = boto3.client('s3')

def get_s3_keys(bucket):

    """Get a list of keys in an S3 bucket."""
    resp = s3.list_objects_v2(Bucket=bucket)
    for obj in resp['Contents']:
      files = obj['Key']
    return files


filename = get_s3_keys('your_bucket_name')

print(filename)

#To print all filenames in a certain directory in a bucket
import boto3

s3 = boto3.client('s3')

def get_s3_keys(bucket, prefix):

    """Get a list of keys in an S3 bucket."""
    resp = s3.list_objects_v2(Bucket=bucket, Prefix=prefix)
    for obj in resp['Contents']:
      files = obj['Key']
      print(files)
    return files


filename = get_s3_keys('your_bucket_name', 'folder_name/sub_folder_name/')

print(filename)
Имран Селим
источник
Оба "get_s3_keys" возвращают только последний ключ.
Алексей Важнов
Это перечисляет все файлы в ведре, хотя; Вопрос был в том, как это сделать ls. Как бы ты это сделал .. только распечатай файлы в корне
Герман
1

С небольшим изменением кода @Hephaeastus в одном из вышеприведенных комментариев, написал метод ниже, чтобы вывести список папок и объектов (файлов) по заданному пути. Работает аналогично команде s3 ls.

from boto3 import session

def s3_ls(profile=None, bucket_name=None, folder_path=None):
    folders=[]
    files=[]
    result=dict()
    bucket_name = bucket_name
    prefix= folder_path
    session = boto3.Session(profile_name=profile)
    s3_conn   = session.client('s3')
    s3_result =  s3_conn.list_objects_v2(Bucket=bucket_name, Delimiter = "/", Prefix=prefix)
    if 'Contents' not in s3_result and 'CommonPrefixes' not in s3_result:
        return []

    if s3_result.get('CommonPrefixes'):
        for folder in s3_result['CommonPrefixes']:
            folders.append(folder.get('Prefix'))

    if s3_result.get('Contents'):
        for key in s3_result['Contents']:
            files.append(key['Key'])

    while s3_result['IsTruncated']:
        continuation_key = s3_result['NextContinuationToken']
        s3_result = s3_conn.list_objects_v2(Bucket=bucket_name, Delimiter="/", ContinuationToken=continuation_key, Prefix=prefix)
        if s3_result.get('CommonPrefixes'):
            for folder in s3_result['CommonPrefixes']:
                folders.append(folder.get('Prefix'))
        if s3_result.get('Contents'):
            for key in s3_result['Contents']:
                files.append(key['Key'])

    if folders:
        result['folders']=sorted(folders)
    if files:
        result['files']=sorted(files)
    return result

Это перечисляет все объекты / папки в данном пути. Folder_path можно оставить равным None по умолчанию, и метод выведет список непосредственного содержимого корня сегмента.

ОЗУ
источник
0

Вот решение

импорт boto3

s3 = boto3.resource ('s3')

BUCKET_NAME = 'Ваше имя S3 Bucket, например,' deletemetesting11 ''

allFiles = s3.Bucket (BUCKET_NAME) .objects.all ()

для файла в allFiles: печать (file.key)

Шаши Кумар Сингх
источник
0

Итак, вы просите эквивалент aws s3 lsв boto3. Это будет список всех папок и файлов верхнего уровня. Это самое близкое, что я мог получить; в нем перечислены только все папки верхнего уровня. Удивительно, насколько сложна такая простая операция.

import boto3

def s3_ls():
  s3 = boto3.resource('s3')
  bucket = s3.Bucket('example-bucket')
  result = bucket.meta.client.list_objects(Bucket=bucket.name,
                                           Delimiter='/')
  for o in result.get('CommonPrefixes'):
    print(o.get('Prefix'))
Герман
источник
0

Вот простая функция, которая возвращает вам имена файлов всех файлов или файлов с определенными типами, такими как «json», «jpg».

def get_file_list_s3(bucket, prefix="", file_extension=None):
            """Return the list of all file paths (prefix + file name) with certain type or all
            Parameters
            ----------
            bucket: str
                The name of the bucket. For example, if your bucket is "s3://my_bucket" then it should be "my_bucket"
            prefix: str
                The full path to the the 'folder' of the files (objects). For example, if your files are in 
                s3://my_bucket/recipes/deserts then it should be "recipes/deserts". Default : ""
            file_extension: str
                The type of the files. If you want all, just leave it None. If you only want "json" files then it
                should be "json". Default: None       
            Return
            ------
            file_names: list
                The list of file names including the prefix
            """
            import boto3
            s3 = boto3.resource('s3')
            my_bucket = s3.Bucket(bucket)
            file_objs =  my_bucket.objects.filter(Prefix=prefix).all()
            file_names = [file_obj.key for file_obj in file_objs if file_extension is not None and file_obj.key.split(".")[-1] == file_extension]
            return file_names
Gench
источник
-1

Это также можно сделать следующим образом:

csv_files = s3.list_objects_v2(s3_bucket_path)
    for obj in csv_files['Contents']:
        key = obj['Key']
KayV
источник