如何使用Python在Amazon S3上删除文件夹及其内容

f0brbegy  于 2023-01-12  发布在  Python
关注(0)|答案(4)|浏览(310)

由于某种原因,我的响应只给了我一个空的方括号,即e [],什么也没发生。
下面是我的代码:

session = boto3.Session(aws_access_key_id=awsaccesskey,aws_secret_access_key=awssecretkey,region_name='eu-west-1')
s3 = session.resource('s3')
b = s3.Bucket(s3bucket)
r = b.objects.filter(Prefix=s3path).delete()
return(r)

更新:根据John的建议,我尝试创建一个测试桶,但不幸的是,我收到了一个权限被拒绝的错误。

  • 在我有权访问的存储桶下创建了一个名为"test"的文件夹
  • 使用前缀='/test/'执行上述代码

这次我收到的是一个ResponseMetadata对象而不是空括号。但是我还是很困惑。我的HTTPStatusCode是200。但是当它告诉我它删除了什么时,它说:

  • '已删除':[{'密钥':"/测试/表名.日期"},{"关键字":"/测试/表格名称. txt "}]}]

我想我不明白这段代码的预期功能。我希望它删除我的空'test'文件夹,我创建了一个根文件夹在我的桶。即桶/test/,但相反,它似乎已经搜索了我的整个桶名为"test"的文件夹,并删除了其中的对象?

kx5bkwkv

kx5bkwkv1#

首先,下面是一些指针:切勿在boto 3客户端对象中硬编码访问凭据。
S3中没有文件夹,而是由键组成了一个扁平的命名空间。但是,在一些程序中,包括AWS控制台,会特别显示名称中带有斜杠的键(例如,请参阅Amazon S3 boto -如何创建文件夹?)。
而不是删除“一个目录”,你可以(也必须)按前缀列出文件并删除。本质上:
对于bucket.list中的关键字(前缀=“your/directory/”):键.delete()
您可以参考此链接,此处捆绑了一个示例:https://docs.aws.amazon.com/code-samples/latest/catalog/python-s3-delete_object.py.html

import logging
import boto3
from botocore.exceptions import ClientError

def delete_object(bucket_name, object_name):
"""Delete an object from an S3 bucket

:param bucket_name: string
:param object_name: string
:return: True if the referenced object was deleted, otherwise False
"""

# Delete the object
s3 = boto3.client('s3')
try:
    s3.delete_object(Bucket=bucket_name, Key=object_name)
except ClientError as e:
    logging.error(e)
    return False
return True
w8ntj3qf

w8ntj3qf2#

client = boto3.client('s3')
response = client.list_objects(
    Bucket='bucket_name',
    Prefix='folder_name/'
)
obj_list = []
for data in response.get('Contents', []):
    print('res', data.get('Key'))
    obj_list.append({'Key': data.get('Key')})
if obj_list:
    response = client.delete_objects(
        Bucket='buket_name',
        Delete={'Objects': obj_list}
    )
    print('response', response)
axzmvihb

axzmvihb3#

我今天一直在寻找这个答案,我非常沮丧,因为这是我的热门答案,但它实际上并没有一个好的解决方案。我意识到这对OP来说已经晚了3年。这里有一个简短的总结,然后是一些令人惊讶的长Python代码来删除某个前缀以下的所有内容。注意,如果你想清空一个 * 整个 * 桶,这段代码可以工作(设置prefix='/'),但是有更有效的方法。2还要注意如果你的bucket打开了版本控制(这是烦人的安全标准坚持的,不管它是否有意义),这并不会删除每个版本。3所以在这个脚本运行之后仍然会有对象版本留下。
重要的是,如果bucket中的对象超过1000个,则必须处理“pagination”,这在here中有详细说明,其思想是可以在一次API调用中获取大量键(最多1000个,但如果你愿意,你可以做更小的页面),然后你必须反复地返回并获取越来越多的页面。2你也可以在一次API调用中删除很多键(同样,最多1000个)。这段代码处理在某个前缀下的所有对象的迭代,一次一个“page”(键组)。它也有一些相当基本的错误处理,增加了几行代码。
要使用这段代码,只需将其保存为文件,更改prefixbucketnamepageSize变量,然后就可以开始比赛了。

import botocore
import boto3

# prefix must NOT start with a /, but MUST end with a slash:
# "prefix/" = OK. "/prefix/" = BAD. "/prefix" = BAD. "prefix" = BAD.
prefix     = "myprefixname/"
bucketname = "mybucketname"
pageSize   = 200 # Will handle this many objects per API call. 1000 is AWS max.

def emptyFolder( bucketname: str, prefix: str):
    """Given a bucket name and prefix, delete all objects in that bucket with
       that prefix. E.g., emptyFolder( "mybucket", "temp" ) will delete all
       objects in s3://mybucket/temp/.
       
        :param bucketname: Name of the bucket
        :param prefix: Prefix of objects to delete. Specify None to delete all objects
        :return: Nothing. Deletes objects.
    """
    page = 0
    iterator = None
    try:
        session = boto3.Session( )
        s3 = session.client('s3')
        paginator = s3.get_paginator( 'list_objects_v2' )
        iterator = paginator.paginate( Bucket=bucketname, Prefix=prefix, 
            PaginationConfig={ 'PageSize': pageSize })
    except botocore.exceptions.ClientError  as e:
        raise Exception("boto3 client error in paginate: " + e.__str__())
    except Exception as e:
        raise Exception("Unexpected error in paginate: " + e.__str__())

    for s3Page in iterator:
        page += 1
        objectList = [{'Key': obj.get('Key')} for obj in s3Page.get('Contents', []) ]
        print( f"Deleting {len(objectList)} objects, page {page}")
        if objectList:
            try:
                response = s3.delete_objects( Bucket=bucketname,
                    Delete={ 'Objects': objectList } )
            except botocore.exceptions.ClientError as e:
                raise Exception("boto3 client error in delete_objects: " + e.__str__())
            except Exception as e:
                raise Exception("Unexpected error in delete_objects: " + e.__str__())
            if( response.get('ResponseMetadata')['HTTPStatusCode'] != 200 ):
                raise Exception("Unexpected HTTP response: " + 
                    response.get('ResponseMetadata')['HTTPStatusCode'] )
if __name__ == "__main__":
    emptyFolder(bucketname=bucketname, prefix=prefix)

我用两个步骤做某事(第24和25行,我得到了boto.Session(),然后得到了session.client(),这实际上可以在一个步骤中完成。原因是我对自己的~/.aws/config文件使用配置文件。所以对我来说,我必须将第24行修改为boto.session( profile_name='myprofile' ),以便在~/.aws/config中调用正确的凭据集。例如,AWS_REGION``AWS_PROFILE等),您不必这样做。

警告

这是相当粗糙的。它会完成工作,但有很多原因会导致它在运行时崩溃。如果有任何错误,它几乎会退出。有时您的凭据是短暂的。(例如,一次只允许颁发15分钟凭证的角色)因此,如果您有数以百万计的对象要删除,在脚本完成工作之前,您的凭据可能会过期,并且它会在中途崩溃,并出现boto ClientError异常。重新启动是安全的。或者您可以使用此脚本,在其基础上构建,并添加新机制以获得具有新临时凭证的新Session()。

yzuktlbb

yzuktlbb4#

import boto3
s3 = boto3.resource('s3')
my_bucket = s3.Bucket('mybucket')

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

相关问题