Boto3 S3 Python脚本报错ValueError: Filename must be a string求解决
分析与解决:S3文件处理中的Filename错误
错误原因拆解
先帮你把问题拆解开,你遇到的ValueError: Filename must be a string,本质是参数传递和S3操作逻辑的双重问题,具体来说:
download_file参数完全用错:你调用s3.Bucket(bucket_name).download_file(Key, file)时,第一个参数Key是'Setting/incoming/'——这只是S3里的路径前缀,不是具体的文件对象键;而且第二个参数file根本没被正确赋值为字符串类型的本地文件名,直接触发了方法的参数校验错误。S3文件遍历逻辑完全错误:代码里
path = s3.Bucket(bucket_name,Key)是瞎写的,boto3的Bucket类初始化只需要桶名,不能传路径前缀;另外os.listdir(path)是用来遍历本地文件夹的,根本没法遍历S3桶里的文件,这部分逻辑从根上就走不通。函数结构混乱:你的
filename函数定义了一堆文件名变量,但既没正确接收传入的参数,也没把「查找文件」「下载文件」「处理文件」这几个步骤分开,导致整个逻辑乱成一团,参数传递自然出问题。
解决办法与修正后的代码
我们重新梳理逻辑:先遍历S3桶中Setting/incoming/前缀下的所有文件,匹配你需要的目标文件,然后依次完成下载、处理、本地保存。
修正后的完整代码
import pandas as pd import fnmatch import time import boto3 import botocore bucket_name = 'data' # 替换为你的桶名 s3_prefix = 'Setting/incoming/' # S3文件前缀路径 date = time.strftime("%Y%m%d") s3 = boto3.resource('s3') def process_s3_files(): # 把需要处理的文件规则统一配置,方便后续修改 file_configs = [ { "pattern": "accountteam_table.csv", "output_name": f'accountteam_table_{date}.csv', "duplicate_subset": 'Account Team Member Id', "drop_columns": [] }, { "pattern": "subscription.csv", "output_name": f'subscriptionproduct_charge_table_{date}.csv', "duplicate_subset": 'Subscription Product & Charge ID', "drop_columns": ['Opportunity Name', 'Account Name', 'Subscription Name'] }, { "pattern": "opportunity.csv", "output_name": f'opportunityproductfamily_table_{date}.csv', "duplicate_subset": 'Opportunity Product Family: ID', "drop_columns": ['Opportunity Name', 'Non-Recurring TCV (OPF) Currency'] } ] # 正确遍历S3指定前缀下的所有文件对象 bucket = s3.Bucket(bucket_name) for obj in bucket.objects.filter(Prefix=s3_prefix): # 提取纯文件名(去掉前缀路径) file_name = obj.key.split('/')[-1] if not file_name: # 跳过前缀本身的空目录对象 continue # 匹配目标文件并处理 for config in file_configs: if fnmatch.fnmatch(file_name, config["pattern"]): local_temp_file = f'temp_{file_name}' try: # 下载文件到本地临时路径,参数完全符合要求 bucket.download_file(obj.key, local_temp_file) print(f"成功下载: {file_name}") # pandas读取与处理 df = pd.read_csv(local_temp_file, delimiter=',', encoding="ISO-8859-1") df.drop_duplicates(subset=config["duplicate_subset"], keep='first', inplace=True) if config["drop_columns"]: df.drop(config["drop_columns"], axis=1, inplace=True) df['date_added'] = "" # 保存处理后的文件 df.to_csv(config["output_name"], sep=',', index=False) print(f"处理完成,已保存为: {config['output_name']}") except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == "404": print(f"文件 {file_name} 在S3中不存在") else: raise # 抛出其他未知错误,方便排查 # 启动处理流程 process_s3_files()
关键修正点
- 正确遍历S3文件:用
bucket.objects.filter(Prefix=s3_prefix)替代错误的os.listdir,这是boto3遍历指定前缀文件的标准方式。 - 参数规范:
download_file的第一个参数是S3对象的完整键obj.key,第二个是明确的字符串类型本地文件名,彻底解决「Filename must be a string」错误。 - 逻辑模块化:把文件匹配规则和处理逻辑封装到配置列表中,代码更清晰,后续新增文件处理也更方便。
- 异常处理优化:保留了404错误的捕获,同时抛出其他未知错误,方便排查潜在问题。
内容的提问来源于stack exchange,提问作者B.W
相关产品推荐
相关产品推荐

