
本文详解如何在使用 boto3 列出 S3 对象时,正确处理子目录(即 key 前缀),避免因错误拼接路径导致“Bucket name must match the regex”异常。核心在于区分合法的存储桶名称与对象键(key)的路径前缀。
本文详解如何在使用 boto3 列出 s3 对象时,正确处理子目录(即 key 前缀),避免因错误拼接路径导致“bucket name must match the regex”异常。核心在于区分**合法的存储桶名称**与**对象键(key)的路径前缀**。
Amazon S3 本身没有真正的“文件夹”概念,所谓子目录(如 FirstLevelS3/SecondLevelS3/)实际是对象键(object key)中的路径前缀(Prefix)。因此,在调用 boto3.resource('s3').Bucket(...) 时,传入的参数必须且只能是合法的存储桶名称——它仅由小写字母、数字、连字符(-)、点号(.)和下划线(_)组成,且不能包含斜杠 / 或其他路径分隔符。
常见错误写法如下(会导致正则校验失败):
import boto3
# ❌ 错误:将路径前缀错误拼接到 bucket 名称中
bucket_from = "BucketSource/FirstLevelS3/SecondLevelS3" # 包含 '/' → 违反 bucket 命名规则
s3 = boto3.resource('s3')
src = s3.Bucket(bucket_from) # 抛出 ValueError: Bucket name must match the regex "^[a-zA-Z0-9.\-_]+"✅ 正确做法是:分离关注点——
-
s3.Bucket(...)只接收纯净的 bucket 名称; - 使用
.objects.filter(Prefix=...)方法筛选具有指定路径前缀的对象。
完整可运行示例:
import boto3
bucket_name = "BucketSource" # ✅ 合法 bucket 名(不含 /)
prefix = "FirstLevelS3/SecondLevelS3/" # ✅ 路径前缀,用于过滤 key
s3 = boto3.resource('s3')
bucket = s3.Bucket(bucket_name)
# 列出该前缀下的所有对象(含递归子路径)
for obj in bucket.objects.filter(Prefix=prefix):
print(obj.key) # 输出如:FirstLevelS3/SecondLevelS3/file1.txt⚠️ 注意事项:
-
Prefix必须以/结尾(若需精确匹配某“文件夹”),否则可能匹配到同名前缀的非目录对象(如data/log会匹配data/logs/xxx和data/logfile); - 若需模拟“列出子目录内容但不递归”,可结合
Delimiter='/'与common_prefixes(适用于client.list_objects_v2()); - 确保 IAM 权限包含
s3:GetObject和s3:ListBucket,且资源策略允许对目标 bucket 及 prefix 的访问。
总结:S3 的“目录”本质是 key 的字符串前缀,绝不可混入 bucket 名。始终遵循 Bucket('name') + .filter(Prefix='path/') 模式,即可安全、高效地遍历任意层级的逻辑子目录。


















