求助:如何用Python从S3 Browser批量导入多份.csv至MySQL?
从S3批量导入CSV文件及文件夹到MySQL的解决方案
前提准备
- 安装依赖包:
pip install boto3 pymysql pandas - 确认AWS账号拥有S3桶的
GetObject和ListBucket权限,MySQL账号具备目标数据库、表的写入权限 - 提前确认MySQL目标表结构与CSV字段匹配,或允许代码自动创建表
核心实现步骤
1. 配置连接参数
import boto3 import pymysql import pandas as pd from io import StringIO # S3配置 s3_bucket = "你的桶名称" s3_folder_path = "csv文件所在的S3前缀/" # 遍历整个桶则留空 # MySQL配置 mysql_host = "你的MySQL主机地址" mysql_user = "MySQL用户名" mysql_password = "MySQL密码" mysql_db = "目标数据库名"
2. 遍历S3中所有CSV文件(含子文件夹)
s3_client = boto3.client('s3') def get_all_s3_csv_files(bucket, prefix): csv_files = [] # 分页遍历S3对象,避免单次请求返回数据过多 paginator = s3_client.get_paginator('list_objects_v2') for page in paginator.paginate(Bucket=bucket, Prefix=prefix): for obj in page.get('Contents', []): if obj['Key'].endswith('.csv'): csv_files.append(obj['Key']) return csv_files target_csv_files = get_all_s3_csv_files(s3_bucket, s3_folder_path)
3. 批量导入CSV到MySQL
提供两种方案,按需选择:
方案一:Pandas写入(适合小文件,代码简洁)
# 建立MySQL连接 mysql_conn = pymysql.connect( host=mysql_host, user=mysql_user, password=mysql_password, database=mysql_db, autocommit=True ) for file_key in target_csv_files: # 从S3读取CSV到内存,避免本地存储 s3_obj = s3_client.get_object(Bucket=s3_bucket, Key=file_key) csv_content = s3_obj['Body'].read().decode('utf-8') df = pd.read_csv(StringIO(csv_content)) # 从文件名提取表名(可根据需求自定义规则) table_name = file_key.split('/')[-1].replace('.csv', '') # 写入MySQL,不存在则创建表 df.to_sql( name=table_name, con=mysql_conn, if_exists='replace', # 可选值:append/replace/fail index=False ) print(f"完成导入:{file_key} → {table_name}") mysql_conn.close()
方案二:MySQL LOAD DATA(适合大文件,性能更优)
import os import tempfile # 必须开启local_infile才能使用LOAD DATA LOCAL mysql_conn = pymysql.connect( host=mysql_host, user=mysql_user, password=mysql_password, database=mysql_db, local_infile=True, autocommit=True ) cursor = mysql_conn.cursor() for file_key in target_csv_files: table_name = file_key.split('/')[-1].replace('.csv', '') # 下载CSV到临时文件,避免占用本地长期存储 with tempfile.NamedTemporaryFile(mode='w+b', suffix='.csv', delete=False) as temp_file: s3_client.download_fileobj(s3_bucket, file_key, temp_file) temp_file_path = temp_file.name try: # 自动创建表(简单字段类型示例,复杂类型需手动调整) s3_obj = s3_client.get_object(Bucket=s3_bucket, Key=file_key) header_line = s3_obj['Body'].readline().decode('utf-8').strip().split(',') create_table_sql = f"CREATE TABLE IF NOT EXISTS {table_name} ({', '.join([f'{col} VARCHAR(255)' for col in header_line])})" cursor.execute(create_table_sql) # 执行LOAD DATA导入 load_sql = f""" LOAD DATA LOCAL INFILE '{temp_file_path}' INTO TABLE {table_name} FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 ROWS; # CSV含表头则添加此行 """ cursor.execute(load_sql) print(f"完成大文件导入:{file_key} → {table_name}") except Exception as e: print(f"导入失败 {file_key}:{str(e)}") finally: # 删除临时文件 os.unlink(temp_file_path) cursor.close() mysql_conn.close()
常见失败原因排查
- S3权限缺失:检查IAM角色是否配置了
s3:GetObject和s3:ListBucket权限 - MySQL连接异常:确认主机可访问、账号密码正确,使用LOAD DATA时需开启
local_infile参数 - CSV格式不统一:检查编码是否为UTF-8、分隔符/引号规则是否一致、表头与表字段是否匹配
- 内存溢出:大文件避免用Pandas全量加载,优先选择LOAD DATA方案
内容的提问来源于stack exchange,提问作者beginofwork
相关产品推荐
相关产品推荐

