Перелік вмісту відра з boto3


198

Як я можу побачити, що знаходиться у відрі у S3 boto3? (тобто робити "ls")?

Виконайте наступне:

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

повертає:

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

Як я бачу його вміст?

Відповіді:


243

Один із способів побачити вміст:

for my_bucket_object in my_bucket.objects.all():
    print(my_bucket_object)

1
Чи можу я отримати ключі під певним шляхом у відрі або з певним роздільником, використовуючи boto3 ??
Рахул КП

109
Ви повинні мати можливість сказати, mybucket.objects.filter(Prefix='foo/bar')і він буде перераховувати лише об'єкти з цим префіксом. Ви також можете передавати Delimiterпараметр.
garnaat

3
не працює з boto3 AttributeError: 'S3' об’єкт не має атрибута 'object'
Shek

2
@garnaat Ваш коментар, в якому згадується, що метод фільтру дійсно мені допоміг (мій код закінчився набагато простіше і швидше) - дякую!
Едвард Діксон

24
Я б радив не використовувати objectяк ім'я змінної, оскільки це затінить глобальний тип object.
Оліланд

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'])

39
Якщо ви також хочете використовувати префікс, ви можете зробити це так:conn.list_objects(Bucket='bucket_name', Prefix='prefix_string')['Contents']
markonovak

13
Це лише список перших 1000 клавіш. З docstring: "Повертає частину або всі (до 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 / облікових даних. Хоча це вірне рішення.
nu everest

6
Це вимагатиме введення секретів для контролю джерел. Не добре.
Ян Грот

2
Ця відповідь нічого не додає щодо API / механіки переліку об'єктів, додаючи невідповідний метод аутентифікації, який є загальним для всіх бото-ресурсів і є помилковою практикою безпеки
Froyke

До відповіді про безпеку додано відмову.
rjurney

Що робити, якщо ключі були надані системою управління ключами та секретами, на зразок Vault (Hashicorp) - хіба це не буде краще, ніж просто розмістити файл облікових даних на ~ / .aws / poveritive?
SunnyAk

26

Для того, щоб обробляти великі списки ключових даних (тобто, коли список каталогів перевищує 1000 елементів), я використовував наступний код для накопичення ключових значень (тобто імен файлів) з декількома списками (завдяки першим рядкам Amelio вище). Код призначений для 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 - це оптимізована версія відповіді @ Гефеста:

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
Daniel Vieira

Це були дві різні взаємодії. 1. Я відредагував вашу відповідь, яка рекомендується навіть при незначних написаннях. Я згоден, що межі між другорядним та тривіальним неоднозначні. Я не забороняю жодної публікації, тому що я бачу помилки, і я цього не робив. Я просто виправляю всі помилки, які я бачу.
petezurich

2. Я схвалив вашу відповідь, тому що ви написали, що files_in_s3це "об'єкт списку". У Python такого немає. Це, скоріше, нестерпно, і я не міг змусити ваш код працювати, і тому я зворотний. Тоді я виявив помилку і побачив вашу точку зору, але не зміг відмовити свою заяву.
petezurich

5
@petezurich жодних проблем, зрозуміло ваше, вказуйте, лише одне, в Python список IS об'єкт, тому що майже все в python є об'єктом, то також випливає, що список також є ітерабельним, але в першу чергу це об’єкт! саме тому я не зрозумів вашу думку - ви проголосували за те, що було правильним, і код, який працює. У будь-якому випадку, дякую за ваше вибачення та все найкраще
Даніель Віейра

1
@petezurich Все в Python є об'єктом. "Список об'єкта" цілком прийнятний.
Зак Гарвуд

4

Підсумок об'єкта:

До ObjectSummary додаються два ідентифікатори:

  • ім'я відра
  • ключ

boto3 S3: Підсумок об’єктів

Детальніше про клавіші об’єктів з документації AWS S3:

Клавіші об'єкта:

Створюючи об’єкт, ви вказуєте ім'я ключа, яке однозначно ідентифікує об'єкт у відрі. Наприклад, на консолі Amazon S3 (див. Консоль управління AWS), коли ви виділяєте відро, з'являється список об'єктів у вашому відрі. Ці назви є клавішами об'єкта. Ім'я ключа - це послідовність символів Unicode, кодування яких UTF-8 становить не більше 1024 байт.

Модель даних Amazon S3 - це плоска структура: ви створюєте відро, а відро зберігає об’єкти. Не існує ієрархії підпапок або підпапок; однак ви можете зробити висновок про логічну ієрархію, використовуючи префікси та роздільники імен ключів, як це робить консоль Amazon S3. Консоль Amazon S3 підтримує концепцію папок. Припустимо, у вашому відрі (створеному адміністратором) чотири об'єкти із наступними клавішами об’єкта:

Розробка / Проекти1.xls

Фінанси / заява1.pdf

Приватний / податковий документ.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()

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

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, наприклад,'deletemetesting11' '

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

для файлу у всіхфайлах: print (file.key)


0

Це також можна зробити так:

csv_files = s3.list_objects_v2(s3_bucket_path)
    for obj in csv_files['Contents']:
        key = obj['Key']

0

Отже, ви запитуєте еквівалент aws s3 lsboto3. Це список усіх папок і файлів верхнього рівня. Це найближче, що я міг отримати; у ньому перелічені лише всі папки верхнього рівня. Дивно, наскільки важка така проста операція.

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'))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.