无法使用 boto3 列出 Scaleway 上的存储桶对象

Lon*_*oub 5 amazon-s3 amazon-web-services python-3.x boto3

我看到了一些类似的帖子,但不幸的是没有一个对我有帮助。我有一个 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)
Run Code Online (Sandbox Code Playgroud)

这段简单的代码会返回一个错误:

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

首先,该错误对我来说似乎不合适,因为我没有指定任何搜索键。我还尝试Prefix向此方法传递一个参数以将搜索范围缩小到特定的子目录,同样的错误。其次,我尝试使用 boto3Resource而不是 来实现相同的目标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)
Run Code Online (Sandbox Code Playgroud)

该代码绝对不会产生任何结果。让我印象深刻的一件奇怪的事情是我没有通过bucket_name这里的任何地方,根据aws 文档,这似乎是正常的

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

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

谢谢

编辑:因此,在记录客户端发送的请求后boto3,我注意到存储桶名称附加到 url 中,因此https://<bucket_name>.s3.<region>.<provider>/它不是 request ,而是 requests https://<bucket_name>.s3.<region>.<provider>/<bucket-name>/,这导致了NoSuchKey错误。我查了一下botocore图书​​馆,发现了这个:

url = _urljoin(endpoint_url, r['url_path'], host_prefix)
Run Code Online (Sandbox Code Playgroud)

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

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

现在还不能令人满意,因为 github 上没有与此相关的问题,我不敢相信该库包含这样的错误,而我是第一个遇到的。

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

小智 6

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

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

list_objects_v2(Bucket=<bucket_name>)
Run Code Online (Sandbox Code Playgroud)


Lon*_*oub 0

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

"ListObjectsV2":{
      "name":"ListObjectsV2",
      "http":{
        "method":"GET",
        "requestUri":"/{Bucket}?list-type=2"
      },
Run Code Online (Sandbox Code Playgroud)

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

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

我做了一个分叉botocore重写了每个端点以删除存储桶名称,如果这可以帮助将来的人。

再次感谢所有贡献者!