使用Boto3将CSV存入S3时的目录判断与属性错误问题
解决S3文件上传的两个问题:路径判断错误与AttributeError
看起来你在使用boto3上传文件到S3时踩了两个典型的坑,我来一步步帮你把代码修正过来:
问题2:AttributeError: 's3.Bucket'对象没有'new_key'属性
这个问题很好解决——boto3的Bucket对象压根就没有new_key这个方法!S3本质是扁平化存储系统,没有真正意义上的“文件夹”,所谓的文件夹都是通过键(Key)里的前缀来模拟的。如果要“创建”文件夹,本质就是上传一个键以/结尾的空对象。
你可以直接用client.put_object()来实现这个操作,比如:
client.put_object(Bucket="outputS3Bucket", Key="folder/newFolder/")
问题1:前缀判断逻辑不准确
你之前用len(result)==0来判断目标路径是否存在,这个逻辑有明显漏洞:只要有任何键的前缀包含你输入的字符串(比如输入folder/ne时,恰好存在folder/neaFo/这样的路径),list_objects就会返回结果,导致误判目标路径存在。
正确的判断方式应该是:
- 使用
list_objects_v2(官方推荐的新版接口,比旧的list_objects更高效可靠) - 设置
Delimiter='/'和Prefix='folder/newFolder/',精准匹配目标路径前缀 - 通过返回结果中的
CommonPrefixes字段,判断是否存在该路径的“文件夹”
修正后的完整代码
import boto3 # 初始化boto3客户端 client = boto3.client('s3') bucket_name = "outputS3Bucket" target_folder = "folder/newFolder/" local_file = "test.csv" target_s3_key = f"{target_folder}test.csv" # 定义检查文件夹是否存在的函数 def is_folder_exists(bucket, folder_prefix): # 确保前缀以/结尾,避免匹配到类似folder/newFolderFile的键 if not folder_prefix.endswith('/'): folder_prefix += '/' # 查询指定前缀的对象,设置分隔符为/来区分文件夹 response = client.list_objects_v2(Bucket=bucket, Prefix=folder_prefix, Delimiter='/') # 存在CommonPrefixes说明有匹配的文件夹,存在Contents说明该前缀的空对象已创建 return 'CommonPrefixes' in response or 'Contents' in response # 检查并创建文件夹 if not is_folder_exists(bucket_name, target_folder): client.put_object(Bucket=bucket_name, Key=target_folder) print(f"已创建目标文件夹: {target_folder}") # 读取本地文件并上传到S3 with open(local_file, 'rb') as f: file_content = f.read() client.put_object(Bucket=bucket_name, Key=target_s3_key, Body=file_content) print(f"文件已成功上传至: s3://{bucket_name}/{target_s3_key}")
额外小提示
其实S3在上传文件时,如果目标键的前缀不存在,会自动处理路径(不需要手动创建文件夹),但如果你明确需要先创建文件夹(比如为了后续配置权限、标记路径存在等逻辑),上面的代码就完全适用啦。
内容的提问来源于stack exchange,提问作者HilaD
相关产品推荐
相关产品推荐

