S3'te "test" adlı bir klasör oluşturdum ve "test_1.jpg", "test_2.jpg" yi "test" e ittim.
"Test" klasörünü silmek için boto'yu nasıl kullanabilirim?
S3'te "test" adlı bir klasör oluşturdum ve "test_1.jpg", "test_2.jpg" yi "test" e ittim.
"Test" klasörünü silmek için boto'yu nasıl kullanabilirim?
Yanıtlar:
Orada hiçbir S3 klasörleri. Bunun yerine, anahtarlar düz bir ad alanı oluşturur. Bununla birlikte, adında eğik çizgi bulunan bir anahtar, AWS konsolu dahil olmak üzere bazı programlarda özel olarak gösterilir (örneğin Amazon S3 boto - nasıl klasör oluşturulur? )
"Bir dizini" silmek yerine, dosyaları öneklere göre listeleyebilir ve silebilirsiniz (ve yapmanız gerekir). Özünde:
for key in bucket.list(prefix='your/directory/'):
key.delete()
Ancak bu sayfadaki diğer başarılı cevaplar daha verimli yaklaşımlar içermektedir.
Önekin sadece kukla dize araması kullanılarak arandığına dikkat edin. Ön ek olsaydı , yani sondaki eğik çizgi eklenmemişse, program da mutlu bir şekilde silerdi your/directory
your/directory-that-you-wanted-to-remove-is-definitely-not-this-one
.
Daha fazla bilgi için bkz.S3 boto liste tuşları bazen dizin anahtarı döndürür.
İşte 2018 (neredeyse 2019) versiyonu:
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.objects.filter(Prefix="myprefix/").delete()
Uzun zaman oldu ve boto3'ün bu hedefe ulaşmak için birkaç farklı yolu olduğunu hissediyorum. Bu, test "klasörünü" ve tüm nesnelerini silmek istediğinizi varsayar. İşte bir yol:
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)
Bu, biri klasördeki nesneleri getirmek, ikincisi ise söz konusu klasördeki tüm nesneleri silmek için iki istekte bulunmalıdır.
https://boto3.readthedocs.org/en/latest/reference/services/s3.html#S3.Client.delete_objects
list_objects
1000'den fazla anahtarı döndüremeyeceğini ve bu kodu birden çok kez çalıştırmanız gerektiğini unutmayın.
boto3
değil boto,
import boto3; def lambda_handler(event, context): '''Code from above'''
. Lambda'nıza S3'ten silme ve zaman aşımını uzatma izni verdiğinizden emin olun.
Kova.delete_keys () 'i bir anahtar listesi ile kullanabilirsiniz ( çok sayıda anahtarla, bunu key.delete kullanmaktan daha büyük bir sıra olarak buldum).
Bunun gibi bir şey:
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)
Patrick'in çözümünde küçük bir gelişme. Bilirsiniz, hem edebileceğiniz gibi list_objects()
ve delete_objects()
1000'de bir nesne sınırı İlanınızı paginate ve topaklar halinde silmek zorunda nedeni budur. Bu oldukça evrenseldir ve verebilir Prefix
üzere paginator.paginate()
silme altdizinler / yollara
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
anahtar kelime paginator.paginate()
See tüm seçenekleri: boto3.readthedocs.io/en/latest/reference/services/...
Prefix
tarafından önerilen filtre ile, silmedenif item is not None
önce bir kontrol eklemem gerekiyordu (S3 öneklerimden bazıları mevcut olmadığından / hiçbir nesneye sahip olmadığından)
S3 klasöründe sürüm oluşturma etkinse:
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket')
bucket.object_versions.filter(Prefix="myprefix/").delete()
files_to_delete = bucket.object_versions.filter(Prefix="myprefix/")
sonra yinelemek files_to_delete
ve print (), sonra delete () çağırmak gibi bir şey yapmanız gerekir.
Benim yaptığım gibi nesne içeriklerine göre filtrelemeye ihtiyaç duyulursa, aşağıdaki mantık için bir plandır:
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})