
本文介绍如何利用 BytesIO 缓冲区将 Matplotlib 生成的图表直接嵌入 Python-docx 创建的 Word 文档中,避免中间生成临时 PNG 文件,提升代码健壮性与执行效率。
本文介绍如何利用 `bytesio` 缓冲区将 matplotlib 生成的图表直接嵌入 python-docx 创建的 word 文档中,避免中间生成临时 png 文件,提升代码健壮性与执行效率。
在使用 python-docx 自动化生成报告时,常需将 Matplotlib 绘制的图表插入 Word 文档。常规做法是先调用 plt.savefig() 将图像写入磁盘(如 chart.png),再通过 doc.add_picture("chart.png") 加载——这不仅引入 I/O 开销,还可能因路径权限、并发写入或清理疏漏引发问题。
幸运的是,python-docx 的 add_picture() 方法并不仅支持文件路径,也接受实现了 seek() 和 read() 方法的二进制流对象(如 io.BytesIO)。而 Matplotlib 的 Figure.savefig() 支持将图像直接写入内存缓冲区,二者结合即可实现“零磁盘落地”的无缝集成。
以下是完整、可复用的实现步骤:
from docx import Document
from docx.shared import Inches
import matplotlib.pyplot as plt
from io import BytesIO
# 1. 创建图表(示例)
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot([1, 2, 3, 4], [1, 4, 2, 3], 'o-', label='Sample Data')
ax.set_title("Direct Embedding Demo")
ax.legend()
ax.grid(True)
# 2. 将图表渲染并写入内存缓冲区(关键步骤)
buffer = BytesIO()
fig.savefig(buffer, format="png", dpi=150, bbox_inches="tight")
buffer.seek(0) # 重置读取指针至起始位置,否则 python-docx 无法读取
# 3. 创建文档并插入图片流
doc = Document()
doc.add_heading("Report with Inline Charts", level=1)
doc.add_picture(buffer, width=Inches(5.5)) # 支持 width/height 参数
doc.save("report_inline_chart.docx")
# 4. 清理资源(推荐)
plt.close(fig) # 防止内存泄漏,尤其在循环绘图场景中
buffer.close()
⚠️ 注意事项:
- 必须在
savefig()后调用buffer.seek(0),否则add_picture()会从缓冲区末尾开始读取,导致空图像或报错; - 推荐显式关闭
Figure(plt.close(fig))和BytesIO对象,避免资源累积; - 若需多图插入,每次均应创建独立
BytesIO实例,不可复用同一缓冲区; -
format="png"是最稳妥选择(Word 原生兼容好),也可尝试"jpeg",但注意透明通道丢失风险。
该方法已广泛应用于自动化报表、实验结果导出及教学材料生成等场景,兼具简洁性、可移植性与生产就绪性。











