Я создал папку в s3 с именем «test» и вставил «test_1.jpg», «test_2.jpg» в «test».
Как я могу использовать boto для удаления папки "test"?
Я создал папку в s3 с именем «test» и вставил «test_1.jpg», «test_2.jpg» в «test».
Как я могу использовать boto для удаления папки "test"?
В S3 нет папок. Вместо этого ключи образуют плоское пространство имен. Однако ключ с косой чертой в названии отображается в некоторых программах, включая консоль AWS (см., Например, Amazon S3 boto - как создать папку?).
Вместо удаления «каталога» вы можете (и должны) перечислять файлы по префиксу и удалять. По сути:
for key in bucket.list(prefix='your/directory/'):
key.delete()
Однако в других завершенных ответах на этой странице представлены более эффективные подходы.
Обратите внимание, что префикс просто ищется с помощью поиска по фиктивной строке. Если бы префикс был , то есть без добавленной косой черты, программа также успешно удалила бы your/directory
your/directory-that-you-wanted-to-remove-is-definitely-not-this-one
.
Для получения дополнительной информации см. Ключи списка ботинок S3 иногда возвращают ключ каталога. а>
Вот версия 2018 (почти 2019):
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
Я чувствую, что прошло много времени, и у boto3 есть несколько различных способов достижения этой цели. Предполагается, что вы хотите удалить "папку" test и все ее объекты. Вот один из способов:
s3 = boto3.resource('s3')
objects_to_delete = s3.meta.client.list_objects(Bucket="MyBucket", Prefix="myfolder/test/")
delete_keys = {'Objects' : []}
delete_keys['Objects'] = [{'Key' : k} for k in [obj['Key'] for obj in objects_to_delete.get('Contents', [])]]
s3.meta.client.delete_objects(Bucket="MyBucket", Delete=delete_keys)
Это должно сделать два запроса: один для извлечения объектов в папке, второй для удаления всех объектов в указанной папке.
https://boto3.readthedocs.org/en/latest/reference/services/s3.html#S3.Client.delete_objects
list_objects
не может вернуть более 1000 ключей, поэтому вам нужно запускать этот код несколько раз.
- person lampslave; 19.04.2016
boto3
, но не в boto
- person avocado; 11.09.2017
import boto3; def lambda_handler(event, context): '''Code from above'''
. Убедитесь, что вы даете Lambda разрешение на удаление из S3 и продлите время ожидания.
- person Nadir Sidi; 27.07.2018
Вы можете использовать bucket.delete_keys () со списком ключей (я обнаружил, что с большим количеством ключей это на порядок быстрее, чем при использовании key.delete).
Что-то вроде этого:
delete_key_list = []
for key in bucket.list(prefix='/your/directory/'):
delete_key_list.append(key)
if len(delete_key_list) > 100:
bucket.delete_keys(delete_key_list)
delete_key_list = []
if len(delete_key_list) > 0:
bucket.delete_keys(delete_key_list)
Небольшое улучшение решения Патрика. Как вы, возможно, знаете, и list_objects()
, и delete_objects()
имеют ограничение на количество объектов 1000. Вот почему вы должны разбивать список на страницы и удалять по частям. Это довольно универсально, и вы можете передать Prefix
paginator.paginate()
для удаления подкаталогов / путей
client = boto3.client('s3', **credentials)
paginator = client.get_paginator('list_objects_v2')
pages = paginator.paginate(Bucket=self.bucket_name)
delete_us = dict(Objects=[])
for item in pages.search('Contents'):
delete_us['Objects'].append(dict(Key=item['Key']))
# flush once aws limit reached
if len(delete_us['Objects']) >= 1000:
client.delete_objects(Bucket=bucket, Delete=delete_us)
delete_us = dict(Objects=[])
# flush rest
if len(delete_us['Objects']):
client.delete_objects(Bucket=bucket, Delete=delete_us)
Prefix
в paginator.paginate()
См. Все параметры: boto3.readthedocs.io/en/latest/reference/services/
- person Chad; 05.06.2018
Prefix
, предложенным @Chad, мне пришлось добавить if item is not None
проверку перед удалением (поскольку некоторые из моих префиксов S3 не существовали / не имели объектов)
- person y2k-shubham; 24.09.2019
Если для сегмента S3 включено управление версиями:
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.object_versions.filter(Prefix="myprefix/").delete()
files_to_delete = bucket.object_versions.filter(Prefix="myprefix/")
, затем перебрать files_to_delete
и вызвать для них print (), а затем delete ().
- person Dan-Dev; 10.12.2020
Если нужно фильтровать по содержимому объекта, как это сделал я, следующая схема вашей логики:
def get_s3_objects_batches(s3: S3Client, **base_kwargs):
kwargs = dict(MaxKeys=1000, **base_kwargs)
while True:
response = s3.list_objects_v2(**kwargs)
# to yield each and every file: yield from response.get('Contents', [])
yield response.get('Contents', [])
if not response.get('IsTruncated'): # At the end of the list?
break
continuation_token = response.get('NextContinuationToken')
kwargs['ContinuationToken'] = continuation_token
def your_filter(b):
raise NotImplementedError()
session = boto3.session.Session(profile_name=profile_name)
s3client = session.client('s3')
for batch in get_s3_objects_batches(s3client, Bucket=bucket_name, Prefix=prefix):
to_delete = [{'Key': obj['Key']} for obj in batch if your_filter(obj)]
if to_delete:
s3client.delete_objects(Bucket=bucket_name, Delete={'Objects': to_delete})