最轻量可行方案是pandas+matplotlib+PdfPages:显式设figure尺寸、每页调用pdf.savefig()后plt.close()、配置中文字体、用plt.table()渲染表格、动态提取时间范围、绘图前校验数据非空。

用 matplotlib + pandas 快速生成带图表的 PDF 报告
直接生成带图表的 PDF,最轻量可行的组合是 pandas 做数据处理 + matplotlib 绘图 + pdfpages.PdfPages 合并多页。不需要引入 reportlab 或 weasyprint 这类重型工具,除非你真要混排 HTML 样式或分栏布局。
常见错误是试图用 plt.savefig() 一张张存图再手动插入 Word/PDF——这既难对齐又无法动态绑定数据。正确做法是:所有图表在内存中绘制,逐页写入 PdfPages 对象。
-
plt.figure(figsize=(8, 5))必须显式设尺寸,否则 PDF 中图表挤压变形(尤其横向报表) - 每页绘图后必须调用
pdf.savefig(),且紧跟着plt.close(),否则内存泄漏、后续图表叠在前一页上 - 中文标签默认不显示,需提前设置:
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans'],并加plt.rcParams['axes.unicode_minus'] = False
把 pandas DataFrame 表格转成 PDF 里的可读表格
pandas.DataFrame.to_html() 生成 HTML 表格再转 PDF 是条死路——样式丢失、列宽失控、跨页断裂。真正稳的方式是用 matplotlib.pyplot.table() 手动渲染表格。
关键点在于控制单元格文本换行和行高:用 cellLoc='center' 避免文字贴边;对长文本列,提前用 df[col].str.wrap(20) 截断换行;整表缩放靠 scale 参数(通常设 0.9~1.2)。
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
立即学习“Python免费学习笔记(深入)”;
- 表头加粗要用
cellColours配合facecolor实现,不能只靠字体加粗——PDF 渲染时加粗可能失效 - 数值列右对齐更专业:构造
colAligns列表,对应每列指定'right'或'left' - 避免用
df.style.format()——它返回的是 Styler 对象,无法直接喂给plt.table()
动态标题和页脚里嵌入日期与数据时间范围
报告标题不能写死“2024年度报告”,得从数据里自动提取时间范围。典型坑是直接用 df['date'].min() 和 df['date'].max()——如果 date 列是字符串或未转为 datetime,结果会是字典序最小/最大值,不是真实时间边界。
- 务必先做类型校验:
assert pd.api.types.is_datetime64_any_dtype(df['date']),否则强制转换:df['date'] = pd.to_datetime(df['date']) - 页脚建议用
fig.text(0.5, 0.02, f'生成时间:{pd.Timestamp("now").strftime("%Y-%m-%d %H:%M")}', ha='center'),比plt.suptitle()更可控 - 标题中年份取
df['date'].dt.year.nunique()判断是否跨年,单一年份就写“2024年度”,否则写“2023–2024年度”
导出前检查图表数据是否为空或全 NaN
生产环境跑定时任务时,某个月份没数据、API 返回空 JSON、ETL 管道中断——这些都会导致图表绘制成空白页或报 ValueError: x and y must be the same length。不能靠 try-except 吞掉错误,而要在绘图前做防御性检查。
- 对折线图/柱状图,检查:
if len(data) == 0 or data.isna().all().all():,然后画一个占位提示框:plt.text(0.5, 0.5, '暂无数据', transform=plt.gca().transAxes, ha='center') - 对饼图,用
data.value_counts(dropna=False)后再判断非零项数,避免NaN占 100% 导致绘图崩溃 - PDF 文件不能留空页:每次
pdf.savefig()前确认 figure 有内容,空图跳过该页
动态报告最难的不是画图,而是让每一页都“知道自己有没有资格出现”。数据质量波动比代码逻辑更常引发失败。

















