我在使用 boto3/aws cli 在不同区域的存储桶之间复制文件时遇到问题(注意:我使用 Scaleway 作为我的云提供商,而不是 AWS)。 我无法使用 boto3 让它工作,但设法使用 rclone 找到解决方案。我想知道 boto3 是否仍然可以限制我的堆栈中的依赖项数量。
使用 Boto3(或 AWS CLI)执行跨区域 S3 复制操作时,Boto3 中的
SourceClient
参数和 AWS CLI 中的 --endpoint-url
参数应用不一致。当尝试将对象从一个区域的源存储桶复制到另一区域的目标存储桶而不将对象下载到本地时,这会导致错误。
预期行为:对象应该成功地从源存储桶跨区域复制到目标存储桶,使用 SourceClient 正确解析源存储桶的区域。
实际行为:出现错误。
botocore.exceptions.ClientError: An error occurred (NoSuchBucket) when calling the CopyObject operation: The specified bucket does not exist
复制命令不使用来自
SourceClient
输入的信息,而仅使用来自调用复制方法的客户端的信息(凭据、位置等)。
我也使用 aws cli 尝试过此操作,但得到了相同的结果:
aws s3 sync s3://source-bucket s3://dest-bucket \
--source-region fr-par \
--region nl-ams \
--endpoint-url https://s3.fr-par.scw.cloud \
--profile mys3profile
aws cli 似乎依赖于 amazonaws 端点:
fatal error: Could not connect to the endpoint URL: "https://source-bucket.s3.fr-par.amazonaws.com/?list-type=2&prefix=&encoding-type=url"
import boto3
from dotenv import dotenv_values
config = dotenv_values(".env")
# Initialize source and destination clients
s3_session = boto3.Session(
aws_access_key_id=config.get("SCW_ACCESS_KEY"),
aws_secret_access_key=config.get("SCW_SECRET_KEY"),
region_name="fr-par",
)
src_s3 = s3_session.client(
service_name="s3",
region_name="fr-par",
endpoint_url="https://s3.fr-par.scw.cloud",
)
s3_session = boto3.Session(
aws_access_key_id=config.get("SCW_ACCESS_KEY"),
aws_secret_access_key=config.get("SCW_SECRET_KEY"),
region_name="nl-ams",
)
dest_s3 = s3_session.client(
service_name="s3",
region_name="nl-ams",
endpoint_url="https://s3.nl-ams.scw.cloud",
)
# Set up source and destination parameters
copy_source = {
"Bucket": "source_bucket_name",
"Key": "source_object_name",
}
# Attempt to copy with SourceClient
dest_s3.copy(
copy_source,
"destination_bucket_name",
source_object_name,
SourceClient=src_s3
)
我无法使用 boto3 让它工作,但我设法使用 rclone 得到了一个我可以接受的解决方案。
要放置在
~.conf/rclone/rclone.conf
中的示例配置:
[scw_s3_fr]
type = s3
provider = Scaleway
access_key_id = ...
secret_access_key = ...
region = fr-par
endpoint = s3.fr-par.scw.cloud
acl = private
[scw_s3_nl]
type = s3
provider = Scaleway
access_key_id = ...
secret_access_key = ...
region = nl-ams
endpoint = s3.nl-ams.scw.cloud
acl = private
将源单向同步到目标:
rclone sync scw_s3_fr:source-bucket scw_s3_nl:destination-bucket -P --metadata --checksum --check-first
有人知道我在这里做错了什么吗?或者可以引导我朝正确的方向进行正确的配置设置。 我的短期需求目前已全部确定,但我想知道是否仍然可以使用纯 boto3 解决方案。
Linux 上的 Python 3.11.2(主要,2023 年 3 月 7 日,16:53:12)[GCC 12.2.1 20230201] boto3='1.35.66'
当尝试在 Scaleway 上不同区域的存储桶之间复制文件时,您遇到的 Boto3 问题会出现,因为 Boto3 中的复制方法与非 AWS S3 实现不完全兼容。具体来说,在使用 Scaleway 时,SourceClient 参数无法正确解析源存储桶的端点,这就是您最终会出现 NoSuchBucket 等错误的原因。
为了让 Boto3 在这种情况下能够进行跨区域复制,你必须自己复制并放置对象,而不是使用副本:
import boto3
from dotenv import dotenv_values
config = dotenv_values(".env")
src_s3 = boto3.client(
service_name="s3",
region_name="fr-par",
endpoint_url="https://s3.fr-par.scw.cloud",
aws_access_key_id=config.get("SCW_ACCESS_KEY"),
aws_secret_access_key=config.get("SCW_SECRET_KEY"),
)
dest_s3 = boto3.client(
service_name="s3",
region_name="nl-ams",
endpoint_url="https://s3.nl-ams.scw.cloud",
aws_access_key_id=config.get("SCW_ACCESS_KEY"),
aws_secret_access_key=config.get("SCW_SECRET_KEY"),
)
source_bucket = "source_bucket_name"
destination_bucket = "destination_bucket_name"
object_key = "source_object_name"
response = src_s3.get_object(Bucket=source_bucket, Key=object_key)
object_data = response["Body"].read()
#Upload after Download
dest_s3.put_object(Bucket=destination_bucket, Key=object_key, Body=object_data)
AWS 复制失败,因为 SourceClient 参数是为特定于 AWS 的跨区域复制而设计的,但由于严格的端点 URL 解析及其对 AWS 特定行为的依赖,不适用于 Scaleway 等非 AWS S3 提供商。