You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()

关键修正点

  1. 正确遍历S3文件:用bucket.objects.filter(Prefix=s3_prefix)替代错误的os.listdir,这是boto3遍历指定前缀文件的标准方式。
  2. 参数规范:download_file的第一个参数是S3对象的完整键obj.key,第二个是明确的字符串类型本地文件名,彻底解决「Filename must be a string」错误。
  3. 逻辑模块化:把文件匹配规则和处理逻辑封装到配置列表中,代码更清晰,后续新增文件处理也更方便。
  4. 异常处理优化:保留了404错误的捕获,同时抛出其他未知错误,方便排查潜在问题。

内容的提问来源于stack exchange,提问作者B.W

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:58:10