在日常的Python开发工作中,我们经常需要将数据、报告或者图表导出为PDF格式。无论是生成财务报表、用户证书、还是系统日志,PDF作为一种通用的文档格式,具有跨平台兼容性好、格式稳定的优势。
本文将从实际项目需求出发,详细介绍如何使用Python生成PDF文档。我们将涵盖从简单的文本PDF到复杂的图表报告生成,帮助你掌握Python PDF生成的核心技术和实战技巧。无论你是刚接触Python开发的新手,还是需要在上位机开发中集成PDF功能的资深开发者,这篇文章都将为你提供实用的解决方案。
在Windows开发环境中,Python生成PDF有以下几个显著优势:
| 库名 | 特点 | 适用场景 |
|---|---|---|
| reportlab | 功能强大,支持复杂布局 | 复杂报告、图表生成 |
| fpdf | 轻量级,易于学习 | 简单文档生成 |
| weasyprint | 支持HTML/CSS转PDF | 网页内容转换 |
| pdfkit | 基于wkhtmltopdf | HTML模板转PDF |
本文将重点介绍reportlab和fpdf两个库的使用方法。
首先安装必要的依赖包:
Bashpip install reportlab pillow matplotlib
reportlab是Python中最强大的PDF生成库,特别适合创建复杂的文档布局。
Pythonfrom reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
from datetime import datetime
import os
def create_basic_pdf():
# 微软雅黑在 Windows 系统一般的路径如下:
font_path = r"C:\Windows\Fonts\msyh.ttc" # .ttf 或 .ttc 结尾都可,ttc表示字体集
# 注册字体(ttc文件需指定字体索引,.ttf不用)
pdfmetrics.registerFont(TTFont("MSYH", font_path))
doc = SimpleDocTemplate("basic_report_msyh.pdf", pagesize=A4)
styles = getSampleStyleSheet()
title_style = ParagraphStyle(
'CustomTitle',
parent=styles['Heading1'],
fontName="MSYH",
fontSize=24,
textColor=colors.darkblue,
alignment=1,
)
normal_style = ParagraphStyle(
'Normal_CN',
parent=styles['Normal'],
fontName="MSYH",
fontSize=12,
)
content = []
content.append(Paragraph("Python PDF生成报告", title_style))
content.append(Spacer(1, 20))
content.append(Paragraph(
f"生成日期:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", normal_style
))
content.append(Spacer(1, 15))
body_text = """
这是一个使用Python reportlab库生成的PDF文档示例。
通过Python编程技巧,我们可以轻松地创建专业的PDF报告。
这种方法特别适合在上位机开发中自动生成各种文档。
"""
content.append(Paragraph(body_text, normal_style))
doc.build(content)
print("✅ 基础PDF生成成功:basic_report_msyh.pdf")
create_basic_pdf()

Pythondef register_chinese_fonts():
"""注册中文字体"""
# Windows系统字体路径
font_paths = [
r'C:\Windows\Fonts\simhei.ttf', # 黑体
r'C:\Windows\Fonts\simsun.ttc', # 宋体
r'C:\Windows\Fonts\msyh.ttc', # 微软雅黑
]
for font_path in font_paths:
if os.path.exists(font_path):
try:
if 'simhei' in font_path:
pdfmetrics.registerFont(TTFont('SimHei', font_path))
return 'SimHei'
elif 'simsun' in font_path:
pdfmetrics.registerFont(TTFont('SimSun', font_path))
return 'SimSun'
elif 'msyh' in font_path:
pdfmetrics.registerFont(TTFont('Microsoft-YaHei', font_path))
return 'Microsoft-YaHei'
except:
continue
# 如果系统字体不可用,使用在线字体
print("⚠️ 系统字体不可用,建议手动下载中文字体")
return None
def create_table_pdf():
"""创建包含表格的PDF文档"""
# 注册中文字体
chinese_font = register_chinese_fonts()
if not chinese_font:
chinese_font = 'Helvetica' # 降级到默认字体
doc = SimpleDocTemplate("table_report.pdf", pagesize=A4)
styles = getSampleStyleSheet()
content = []
# 创建自定义样式支持中文
from reportlab.lib.styles import ParagraphStyle
chinese_title_style = ParagraphStyle(
'ChineseTitle',
parent=styles['Title'],
fontName=chinese_font,
fontSize=16,
alignment=1, # 居中
)
# 标题
title = Paragraph("销售数据报表", chinese_title_style)
content.append(title)
content.append(Spacer(1, 0.3 * inch))
# 模拟数据
data = [
['产品名称', '销售数量', '单价(元)', '总金额(元)'],
['iPhone 14', '120', '6999', '839,880'],
['MacBook Pro', '85', '12999', '1,104,915'],
['iPad Air', '200', '4599', '919,800'],
['AirPods Pro', '300', '1999', '599,700'],
['', '', '合计:', '3,464,295']
]
# 创建表格
table = Table(data, colWidths=[2 * inch, 1 * inch, 1 * inch, 1.5 * inch])
# 设置表格样式
table.setStyle(TableStyle([
# 表头样式
('BACKGROUND', (0, 0), (-1, 0), colors.darkblue),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('FONTNAME', (0, 0), (-1, 0), chinese_font), # 使用中文字体
('FONTSIZE', (0, 0), (-1, 0), 12),
# 数据行样式
('BACKGROUND', (0, 1), (-1, -2), colors.beige),
('FONTNAME', (0, 1), (-1, -1), chinese_font), # 使用中文字体
('FONTSIZE', (0, 1), (-1, -1), 10),
# 合计行样式
('BACKGROUND', (0, -1), (-1, -1), colors.lightgrey),
('FONTNAME', (0, -1), (-1, -1), chinese_font), # 使用中文字体
# 边框
('GRID', (0, 0), (-1, -1), 1, colors.black),
('LINEBELOW', (0, 0), (-1, 0), 2, colors.darkblue),
]))
content.append(table)
# 构建PDF
doc.build(content)
print("✅ 表格PDF生成成功:table_report.pdf")
Pythonimport matplotlib.pyplot as plt
import matplotlib
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from reportlab.platypus.para import Paragraph
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
import os
matplotlib.use('Agg') # 使用非交互式后端
from reportlab.platypus import Image, SimpleDocTemplate, Spacer
import io
def setup_chinese_fonts():
"""设置中文字体"""
# 设置matplotlib中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# 设置ReportLab中文字体
font_paths = [
r'C:\Windows\Fonts\simhei.ttf', # 黑体
r'C:\Windows\Fonts\msyh.ttc', # 微软雅黑
r'C:\Windows\Fonts\simsun.ttc', # 宋体
]
for font_path in font_paths:
if os.path.exists(font_path):
try:
if 'simhei' in font_path:
pdfmetrics.registerFont(TTFont('SimHei', font_path))
return 'SimHei'
elif 'msyh' in font_path:
pdfmetrics.registerFont(TTFont('Microsoft-YaHei', font_path))
return 'Microsoft-YaHei'
elif 'simsun' in font_path:
pdfmetrics.registerFont(TTFont('SimSun', font_path))
return 'SimSun'
except:
continue
return 'Helvetica' # 如果没有找到中文字体,返回默认字体
def create_chart_pdf():
"""创建包含图表的PDF文档"""
# 设置中文字体
chinese_font = setup_chinese_fonts()
doc = SimpleDocTemplate("chart_report.pdf", pagesize=A4)
styles = getSampleStyleSheet()
content = []
# 创建支持中文的样式
chinese_title_style = ParagraphStyle(
'ChineseTitle',
parent=styles['Title'],
fontName=chinese_font,
fontSize=16,
alignment=1, # 居中
)
chinese_normal_style = ParagraphStyle(
'ChineseNormal',
parent=styles['Normal'],
fontName=chinese_font,
fontSize=12,
leading=16, # 行间距
)
# 标题
title = Paragraph("数据分析图表报告", chinese_title_style)
content.append(title)
content.append(Spacer(1, 0.3 * inch))
# 生成matplotlib图表
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4))
# 柱状图
products = ['iPhone', 'MacBook', 'iPad', 'AirPods']
sales = [120, 85, 200, 300]
ax1.bar(products, sales, color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4'])
ax1.set_title('产品销售数量')
ax1.set_ylabel('销售数量')
# 设置x轴标签旋转,避免重叠
ax1.tick_params(axis='x', rotation=45)
# 饼图
sizes = [25, 30, 20, 25]
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4']
ax2.pie(sizes, labels=products, colors=colors, autopct='%1.1f%%')
ax2.set_title('市场份额分布')
plt.tight_layout()
# 保存图表到内存
img_buffer = io.BytesIO()
plt.savefig(img_buffer, format='png', dpi=300, bbox_inches='tight')
img_buffer.seek(0)
plt.close()
# 将图表添加到PDF
img = Image(img_buffer, width=6 * inch, height=2.4 * inch)
content.append(img)
content.append(Spacer(1, 0.3 * inch))
# 添加分析说明 - 使用正确的HTML标签
analysis_lines = [
"<b>数据分析总结:</b>",
"1. AirPods产品销量最高,达到300件",
"2. MacBook销量相对较低,但单价较高",
"3. 各产品市场份额分布相对均衡",
"4. 建议加强MacBook的市场推广"
]
# 为每行创建单独的段落
for line in analysis_lines:
analysis_para = Paragraph(line, chinese_normal_style)
content.append(analysis_para)
content.append(Spacer(1, 0.1 * inch))
# 构建PDF
doc.build(content)
print("✅ 图表PDF生成成功:chart_report.pdf")
if __name__ == "__main__":
create_chart_pdf()

通过本文的详细介绍,我们掌握了Python生成PDF的核心技术和实战技巧。让我们来总结三个关键要点:
1. 选择合适的工具库:根据项目需求选择reportlab(复杂文档),合理的工具选择是成功的一半。
2. 注重代码结构设计:通过模块化设计、异常处理和性能优化,确保生成的PDF既稳定又高效,这在上位机开发中尤为重要。
3. 掌握实用技巧:从基础的文本PDF到复杂的图表报告,再到批量生成和中文支持,这些编程技巧将大大提升你的开发效率。
Python PDF生成技术在实际项目中应用广泛,掌握这些技能将让你在Python开发的道路上更加游刃有余。建议大家在实际项目中多加练习,结合具体业务需求来优化代码结构。
如果你在实际应用中遇到问题,欢迎在评论区分享交流。让我们一起在Python开发的路上不断进步!
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!