Python实现Redshift数据高效导出到Excel文件的多Sheet
下面结合Python及相关库(pandas、redshift_connector、awswrangler、openpyxl、boto3、pathlib 和 datetime)实现从本地读取Parquet文件、从Amazon Redshift导出数据到S3并下载、合并 两个DataFrame并按指定列排序后导出至Excel文件(一个文件多个Sheet)的完整数据工程流程,并展开详细论述。所有涉及的库与实现思路均可在生产环境或数据分析项目中直接复用。
1. 环境准备
首先安装所需依赖包,并导入相关库:
pip install pandas pyarrow redshift_connector awswrangler openpyxl boto3
import os import pandas as pd import redshift_connector import awswrangler as wr import boto3 from datetime import datetime from pathlib import Path
2. 从本地Parquet读取DataFrame(df_1)
利用 pandas.read_parquet 从本地读取parquet文件并将其加载为DataFrame:
parquet_path = "./data/source_data.parquet" df_1 = pd.read_parquet(parquet_path, engine="pyarrow")
read_parquet 默认使用 pyarrow 引擎,该引擎对列式存储的parquet文件有较好的性能表现。在处理大规模数据时,可通过设置 use_threads=True 启用多线程读取,或通过 memory_map=True 使用内存映射文件以提升读取速度。
3. 从Amazon Redshift通过UNLOAD导出数据到S3并下载为DataFrame(df_2)
此部分整合了 redshift_connector、awswrangler、boto3、pathlib 和 datetime 等库的功能。
3.1 建立Redshift连接
使用 redshift_connector 创建与Amazon Redshift集群的连接:
conn = redshift_connector.connect(
host=os.getenv("REDSHIFT_HOST"),
database=os.getenv("REDSHIFT_DATABASE"),
port=int(os.getenv("REDSHIFT_PORT", 5439)),
user=os.getenv("REDSHIFT_USER"),
password=os.getenv("REDSHIFT_PASSWORD")
)此方式基于AWS凭证进行认证,符合Amazon Redshift Python连接器的标准用法。
3.2 利用awswrangler执行UNLOAD操作
awswrangler.redshift.unload_to_files 封装了Redshift的 UNLOAD 命令,可将查询结果直接导出至S3(支持CSV或Parquet格式),适用于大规模数据导出场景。
使用带时间戳的S3路径以规避文件名冲突:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
s3_unload_path = f"s3://your-bucket/redshift_unload/{timestamp}/"
sql_query = """
SELECT
id,
column_a,
column_b,
created_at
FROM your_schema.your_table
WHERE created_at>= '2026-01-01'
"""
wr.redshift.unload_to_files(
sql=sql_query,
path=s3_unload_path,
con=conn,
iam_role=os.getenv("REDSHIFT_IAM_ROLE"),
unload_format="PARQUET",
parallel=True,
region=os.getenv("AWS_REGION", "us-east-1")
)UNLOAD路径设计说明:通过在S3路径中嵌入 datetime.now().strftime("%Y%m%d_%H%M%S") 生成的时间戳,可确保每次运行生成唯一路径,防止多次执行之间的文件覆盖。也可在UNLOAD命令中使用 ALLOWOVERWRITE 参数覆盖已有文件,但通过时间戳隔离版本是更为稳健的做法。
参数说明:
- sql:执行的查询语句,支持任意复杂的SELECT语句。
- path:S3目标路径,UNLOAD会在此路径下生成一个或多个数据文件。
- con:通过 redshift_connector 建立的连接对象。
- iam_role:具有写入目标S3桶权限的IAM角色ARN,该角色至少需要 s3:PutObject 和 s3:ListBucket 权限。
- unload_format:导出格式,支持 "CSV" 或 "PARQUET",此处选用 "PARQUET" 以获得更高的压缩率和更快的后续读取速度。
- parallel:是否并行写入多个文件,默认 True 可充分利用Redshift集群的切片数提升导出速度。
- region:S3桶所在的AWS区域。
3.3 从S3下载并读取为DataFrame
UNLOAD执行完毕后,使用 boto3 列出S3路径下生成的文件,并通过 awswrangler.s3.read_parquet 直接读取S3上的parquet文件为DataFrame:
session = boto3.Session(region_name=os.getenv("AWS_REGION", "us-east-1"))
df_2 = wr.s3.read_parquet(path=s3_unload_path, boto3_session=session)awswrangler.s3.read_parquet 可以自动识别S3路径下的所有parquet文件并将它们合并为单个DataFrame,极大简化了S3数据读取流程。
3.4 关闭Redshift连接
conn.close()
4. 统一按id列排序
两个DataFrame均按照 id 列升序排列,以确保写入Excel后的数据具备一致性:
df_1 = df_1.sort_values(by="id", ascending=True, ignore_index=True) df_2 = df_2.sort_values(by="id", ascending=True, ignore_index=True)
ignore_index=True 可重置索引,避免将旧索引带入Excel输出。
5. 将两个DataFrame写入同一Excel文件的不同Sheet
使用 pd.ExcelWriter 配合 openpyxl 引擎(支持 .xlsx 格式),将两个DataFrame分别写入不同Sheet:
output_path = Path("./output/mult_sheets_1.xlsx")
output_path.parent.mkdir(parents=True, exist_ok=True)
with pd.ExcelWriter(output_path, engine="openpyxl") as writer:
df_1.to_excel(writer, sheet_name="df_1", index=False)
df_2.to_excel(writer, sheet_name="df_2", index=False)with 语句可确保Excel文件在写入完成后自动保存并关闭。sheet_name 分别设置为 "df_1" 和 "df_2",index=False 避免将行索引写入Excel。如需在同一文件内写入更多DataFrame,只需继续调用 to_excel 方法即可。
6. 完整代码示例
将上述各模块整合为完整可运行的代码:
import os
import pandas as pd
import redshift_connector
import awswrangler as wr
import boto3
from datetime import datetime
from pathlib import Path
# ---------- 配置 ----------
parquet_path = "./data/source_data.parquet"
output_path = Path("./output/mult_sheets_1.xlsx")
output_path.parent.mkdir(parents=True, exist_ok=True)
sql_query = """
SELECT
id,
column_a,
column_b,
created_at
FROM your_schema.your_table
WHERE created_at>= '2026-01-01'
"""
# ---------- 1. 读取本地Parquet(df_1) ----------
df_1 = pd.read_parquet(parquet_path, engine="pyarrow")
# ---------- 2. 连接Redshift ----------
conn = redshift_connector.connect(
host=os.getenv("REDSHIFT_HOST"),
database=os.getenv("REDSHIFT_DATABASE"),
port=int(os.getenv("REDSHIFT_PORT", 5439)),
user=os.getenv("REDSHIFT_USER"),
password=os.getenv("REDSHIFT_PASSWORD")
)
# ---------- 3. UNLOAD到S3 ----------
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
s3_unload_path = f"s3://your-bucket/redshift_unload/{timestamp}/"
wr.redshift.unload_to_files(
sql=sql_query,
path=s3_unload_path,
con=conn,
iam_role=os.getenv("REDSHIFT_IAM_ROLE"),
unload_format="PARQUET",
parallel=True,
region=os.getenv("AWS_REGION", "us-east-1")
)
# ---------- 4. 从S3读取为DataFrame(df_2) ----------
session = boto3.Session(region_name=os.getenv("AWS_REGION", "us-east-1"))
df_2 = wr.s3.read_parquet(path=s3_unload_path, boto3_session=session)
# ---------- 5. 关闭Redshift连接 ----------
conn.close()
# ---------- 6. 按id排序 ----------
df_1 = df_1.sort_values(by="id", ascending=True, ignore_index=True)
df_2 = df_2.sort_values(by="id", ascending=True, ignore_index=True)
# ---------- 7. 写入Excel ----------
with pd.ExcelWriter(output_path, engine="openpyxl") as writer:
df_1.to_excel(writer, sheet_name="df_1", index=False)
df_2.to_excel(writer, sheet_name="df_2", index=False)
print(f"Excel文件已生成:{output_path}")7. 常见问题与调试建议
7.1 UNLOAD权限错误
执行UNLOAD时若遇到 AccessDenied 错误,请检查 iam_role 对应的IAM角色是否具备以下权限:
- s3:PutObject(允许写入S3对象)
- s3:ListBucket(允许列出桶内对象)
7.2 区域不匹配
若S3桶与Redshift集群位于不同AWS区域,需通过 region 参数明确指定S3桶所在区域,否则UNLOAD将失败。
7.3 时间戳路径覆盖问题
如需在同一路径下多次运行,建议保留时间戳前缀,避免使用 ALLOWOVERWRITE 参数以防止意外覆盖历史数据。同时可在脚本末尾添加S3清理逻辑,定期删除过期的UNLOAD临时文件以控制存储成本。
7.4 性能优化建议
UNLOAD并行度:parallel=True 可显著提升大数据量的导出速度,但如果后续处理对文件顺序有严格要求,可设置 parallel=False 并按 ORDER BY 子句生成单一有序文件。
Parquet读取:若 df_2 数据量极大,可使用 wr.s3.read_parquet 的 chunked=True 参数实现分块读取,降低内存压力。
内存映射:对于本地parquet文件的读取,可通过 pd.read_parquet(..., memory_map=True) 减少内存开销。
8. 扩展建议
以上流程可作为日常数据分析 或ETL任务的基础模板。如需进一步工程化,可考虑:
- 参数化配置:将S3桶名、Redshift连接信息、SQL查询等提取为配置文件或环境变量,提升代码的可移植性。
- 日志记录:引入Python内置的 logging 模块,记录UNLOAD耗时、DataFrame行数等关键指标。
- 错误重试机制:对UNLOAD和S3读取操作添加重试逻辑,增强脚本在临时网络波动下的鲁棒性。
- S3临时文件清理:UNLOAD完成后可选择性地删除S3上的临时文件以控制存储成本,可通过 wr.s3.delete_objects 实现。
- 多Sheet样式定制:若需要对Excel输出进行样式设置(如列宽、字体、颜色),可使用 openpyxl 或 xlsxwriter 的高级接口对每个Sheet单独定制。
此方案覆盖了从本地数据读取、云端数据仓库导出、云存储中转、本地合并到最终Excel输出的全链路,适用于数据分析报告生成、数据质量比对、多源数据融合等业务场景。
以上就是Python实现Redshift数据高效导出到Excel文件的多Sheet的详细内容,更多关于Python数据导出到Excel的资料请关注脚本之家其它相关文章!
相关文章
Python os模块中的isfile()和isdir()函数均返回false问题解决方法
这篇文章主要介绍了Python os模块中的isfile()和isdir()函数均返回false问题解决方法,返回false的原因是路径使用了相对路径,使用绝对路径就可以解决这个问题,需要的朋友可以参考下2015-02-02
Django model重写save方法及update踩坑详解
这篇文章主要介绍了Django model重写save方法及update踩坑详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2020-07-07


最新评论