如何轻松确定Boto 3 S3存储桶资源是否存在?

65

例如,我有这段代码:

import boto3

s3 = boto3.resource('s3')

bucket = s3.Bucket('my-bucket-name')

# Does it exist???
6个回答

90
在撰写本文时,没有一种高级方法可以快速检查存储桶是否存在并且您有权限访问它,但是您可以进行低级别的调用HeadBucket操作。 这是执行此检查最便宜的方法:
from botocore.client import ClientError

try:
    s3.meta.client.head_bucket(Bucket=bucket.name)
except ClientError:
    # The bucket does not exist or you have no access.

或者,您也可以重复调用create_bucket。该操作是幂等的,因此它将创建或仅返回现有存储桶,这在检查存在性以确定是否应创建存储桶时非常有用:

bucket = s3.create_bucket(Bucket='my-bucket-name')

请务必查看官方文档

注意:在版本0.0.7之前,meta是一个Python字典。


这也是检查对象是否存在的最佳方法吗?调用head_object()并处理错误?相对于key in bucket.objects.all()?(特别是如果您不打算实际get()该对象?) - Christopher Pearson
2
通常最好使用head_object(),因为它只会执行一次小型请求,而使用bucket.objects.all()将获取所有对象信息(这可能需要多个页面的结果的多个请求),然后在这些结果中查找您的键是否存在。@ChristopherPearson - Daniel
12
小小澄清一下:create_bucket() 在除了美国东部(弗吉尼亚北部)区域以外的所有 AWS 区域中都会返回 BucketAlreadyOwnedByYou 错误, 而在 us-east-1 区域中会得到 200 OK 响应。实际上,使用 head_object() 才是正确的方法 - lec00q
2
不幸的是,在不同区域创建的现有存储桶上调用create_bucket将引发以下异常: ClientError:调用CreateBucket操作时发生错误(BucketAlreadyOwnedByYou):您先前创建命名存储桶的请求成功,并且您已经拥有它。 - siesta
文档的直接链接:http://boto3.readthedocs.io/en/latest/guide/migrations3.html#accessing-a-bucket - Cjkjvfnby

38

我已经成功尝试过这个:

import boto3

s3 = boto3.resource('s3')
bucket = s3.Bucket('my-bucket-name')

if bucket.creation_date:
   print("The bucket exists")
else:
   print("The bucket does not exist")

8
我认为这是最佳解决方案,因为:1)它不需要使用可能很昂贵的ListBuckets;2)它不需要降到低级客户端API。 - Oliver
@ciastek,你误解了重点。@Oliver的意思是,作为程序员,你不必直接使用低级客户端来执行此操作。当然,在内部它可能会发出调用,但对程序员来说是不可见的。请返回并重新阅读问题和答案。 - Urda
3
有人知道获取s3.Bucket().creation_date所需的最小权限操作是什么吗? - Shawn
2
获取一个存在且可以上传的存储桶的creation_dateNone - Fabien Snauwaert
2
P.S.:好半个小时后,“creation_date”不再是“None”。这是一个新的存储桶,所以我认为在存储桶创建后会有一些延迟。 - Fabien Snauwaert

35

如@Daniel所提及的,根据Boto3文档建议的最佳方法是使用head_bucket()

head_bucket() - 此操作有助于确定存储桶是否存在且您有权限访问它

如果您只有少量的存储桶,则可以使用以下方法:

>>> import boto3
>>> s3 = boto3.resource('s3')
>>> s3.Bucket('Hello') in s3.buckets.all()
False
>>> s3.Bucket('some-docs') in s3.buckets.all()
True
>>> 

7
假设您是存储桶的所有者,那么这个方法可以奏效。但是它将调用ListBuckets操作,比HeadBucket操作稍微昂贵一些。对于低调用量,成本相同,但如果您检查许多存储桶,随着时间的推移,成本会逐渐增加!此外,集合在解析响应后创建资源实例,而head_bucket调用只返回低级响应,不进行额外处理。 - Daniel

29

我尝试了Daniel的示例,它非常有帮助。接着按照boto3文档编写了我的测试代码。我添加了一个检查,用于处理私有存储桶返回“Forbidden!”错误的情况。

import boto3, botocore
s3 = boto3.resource('s3')
bucket_name = 'some-private-bucket'
#bucket_name = 'bucket-to-check'

bucket = s3.Bucket(bucket_name)
def check_bucket(bucket):
    try:
        s3.meta.client.head_bucket(Bucket=bucket_name)
        print("Bucket Exists!")
        return True
    except botocore.exceptions.ClientError as e:
        # If a client error is thrown, then check that it was a 404 error.
        # If it was a 404 error, then the bucket does not exist.
        error_code = int(e.response['Error']['Code'])
        if error_code == 403:
            print("Private Bucket. Forbidden Access!")
            return True
        elif error_code == 404:
            print("Bucket Does Not Exist!")
            return False

check_bucket(bucket)

希望这对像我一样刚接触boto3的新手有所帮助。


-3
使用查找函数 -> 如果存储桶存在,则返回None
if s3.lookup(bucketName) is None:
    bucket=s3.create_bucket(bucketName) # Bucket Don't Exist
else:
    bucket = s3.get_bucket(bucketName) #Bucket Exist

1
boto3的S3客户端或资源API中没有查找功能。 - Atif

-4

你可以使用 conn.get_bucket

from boto.s3.connection import S3Connection
from boto.exception import S3ResponseError    

conn = S3Connection(aws_access_key, aws_secret_key)

try:
    bucket = conn.get_bucket(unique_bucket_name, validate=True)
except S3ResponseError:
    bucket = conn.create_bucket(unique_bucket_name)

引用http://boto.readthedocs.org/en/latest/s3_tut.html中的文档:

自Boto v2.25.0开始,这现在执行HEAD请求(更便宜但错误消息更糟糕)。


1
这个不是针对boto3而不是boto吗? - Christopher Pearson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接