【问题标题】:Can't list bucket objects on Scaleway using boto3无法使用 boto3 在 Scaleway 上列出存储桶对象
【发布时间】:2021-02-23 13:00:22
【问题描述】:

我看到了一些类似的帖子,但不幸的是没有一个对我有帮助。 我有一个 s3 存储桶(在 scaleway 上),我试图简单地列出该存储桶中包含的所有对象,使用 boto3 s3 客户端如下:

s3 = boto3.client('s3',
                  region_name=AWS_S3_REGION_NAME,
                  endpoint_url=AWS_S3_ENDPOINT_URL,
                  aws_access_key_id=AWS_ACCESS_KEY_ID,
                  aws_secret_access_key=AWS_SECRET_ACCESS_KEY
                  )

all_objects = s3.list_objects_v2(Bucket=AWS_STORAGE_BUCKET_NAME)

这段简单的代码以错误响应:

botocore.errorfactory.NoSuchKey: An error occurred (NoSuchKey) when calling the ListObjects operation: The specified key does not exist.

首先,这个错误对我来说似乎不合适,因为我没有指定任何搜索键。我还尝试将Prefix 参数传递给此方法,以将搜索范围缩小到特定的子目录,同样的错误。 其次,我尝试使用 boto3 Resource 而不是 Client 来实现相同的目的,如下:

session = boto3.Session(
    region_name=AWS_S3_REGION_NAME,
    aws_access_key_id=AWS_ACCESS_KEY_ID,
    aws_secret_access_key=AWS_SECRET_ACCESS_KEY
)
resource = session.resource(
    's3',
    endpoint_url=AWS_S3_ENDPOINT_URL,
)

for bucket in resource.buckets.all():
    print(bucket.name)

该代码绝对不会产生任何结果。令我震惊的一件奇怪的事情是,我在这里的任何地方都没有通过bucket_name,这在aws documentation看来是正常的

我不可能错误地配置客户端,因为我可以在同一个客户端上完美地使用put_object 方法。一个奇怪的地方是:当我想放置一个文件时,我将整个路径传递给put_object 作为Key (因为我发现它是要走的路),但是插入的对象带有预先添加的存储桶名称.所以假设我调用put_object(Key='/path/to/myfile.ext'),对象最终将是/bucket-name/path/to/myfile.ext

这种奇怪的行为是我问题的关键吗?我该如何调查正在发生的事情,或者是否有其他方法可以尝试列出存储桶文件?

谢谢

编辑:所以,在记录boto3 客户端发送的请求后,我注意到存储桶名称附加到 url,所以它请求 https://<bucket_name>.s3.<region>.<provider>/<bucket-name>/,而不是请求 https://<bucket_name>.s3.<region>.<provider>/<bucket-name>/,这导致NoSuchKey 错误。 我查看了botocore 库,发现了这个:

url = _urljoin(endpoint_url, r['url_path'], host_prefix)

botocore.awsrequest 第 252 行,其中 r['url_path'] 包含 /skichic-bucket?list-type=2。所以从这里开始,我应该能够轻松地修补库核心以使其适合我。

另外,Prefix 参数不起作用,无论我传递给它什么,我总是会收到整个存储桶内容,但我想我也可以轻松地修补它。

现在不满意,因为github上没有相关的问题,我不敢相信库中包含我是第一个遇到的错误。

谁能解释这整个混乱? >.

【问题讨论】:

  • 最后一个 sn-p 代码不会尝试列出存储桶对象,它会列出您账户中给定区域的所有 S3 存储桶。
  • @jordanm 是的,你是对的,但它没有返回任何东西
  • AWS_S3_ENDPOINT_URL 包含什么?覆盖默认值并不常见。
  • @jordanm OP 使用的是S3-compatible Object Storage - Scaleway,因此需要指定一个端点。

标签: python-3.x amazon-web-services amazon-s3 boto3


【解决方案1】:

你可以试试这个。你必须使用你的资源而不是我的 s3sr。

s3sr = resource('s3')
bucket = 'your-bucket'
prefix = 'your-prefix/' # if no prefix, pass ''

def get_keys_from_prefix(bucket, prefix):
    '''gets list of keys for given bucket and prefix'''
    keys_list = []
    paginator = s3sr.meta.client.get_paginator('list_objects_v2')
    # use Delimiter to limit search to that level of hierarchy
    for page in paginator.paginate(Bucket=bucket, Prefix=prefix, Delimiter='/'):
        keys = [content['Key'] for content in page.get('Contents')]
        print('keys in page: ', len(keys))
        keys_list.extend(keys)
    return keys_list

keys_list = get_keys_from_prefix(bucket, prefix)

【讨论】:

  • 感谢您的回答!不幸的是,它引发了同样的错误botocore.errorfactory.NoSuchKey。我想我要问问 scaleway 支持,也许他们的 s3 集成有问题?
  • 我查看了 scaleway 链接,boto3 看起来不支持。提到了 Aws 命令行以及其他方法。祝你好运。
  • 在这个 example 他们使用 boto3 所以我认为它应该可以工作
  • 点了。想知道您是否按原样使用该示例,看看您是否可以创建一个预签名的 url。并使用请求来获取对象。此外,您对会话和客户端的实现略有不同。也许尝试使用他们使用的确切语法。
  • @Jonathan Leon scaleway 的实现肯定有些奇怪。我将解释我在答案中发现的内容,并附上我制作的来自 botocore 的 fork 的链接。
【解决方案2】:

在仔细研究之后,我发现(很多)botocore 服务端点模式以存储桶名称开头。例如,这里是list_objects_v2 服务的定义:

"ListObjectsV2":{
      "name":"ListObjectsV2",
      "http":{
        "method":"GET",
        "requestUri":"/{Bucket}?list-type=2"
      },

我的猜测是,在 AWS S3 的标准实现中,有一个 genericendpoint_url(解释了@jordanm 注释),并且通过端点到达目标存储桶。

现在,对于 Scaleway,每个存储桶都有一个 endpoint_url,存储桶名称包含在该 url 中(例如 https://<bucket_name>.s3.<region>.<provider>),并且任何端点都应该直接以存储桶 Key 开头。

我创建了botocore 中的fork,在那里我重写了每个端点以删除存储桶名称,如果这对将来的某人有帮助的话。

再次感谢所有贡献者!

【讨论】:

    【解决方案3】:

    对于那些面临同样问题的人,请尝试将您的 boto3 客户端或资源实例中的 endpoint_url 参数从 https://<bucket_name>.s3.<region>.<provider> 更改为 https://s3.<region>.<provider> Scaleway:https://s3.<region>.scw.cloud

    然后您可以设置Bucket 参数来选择您想要的存储桶。

    list_objects_v2(Bucket=<bucket_name>)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-28
      • 2015-07-26
      • 2021-11-25
      • 1970-01-01
      • 1970-01-01
      • 2021-05-09
      • 2018-03-29
      • 1970-01-01
      相关资源
      最近更新 更多