Python Reportlab中拉丁字符čćžšđ显示乱码如何解决
核心问题定位
你遇到的乱码由两个直接错误导致:
- 多余的手动编码操作:你对非ASCII字符串调用
.encode('utf-8')将Unicode字符串转为了bytes类型,Reportlab的Paragraph组件仅接收原生字符串类型输入,传入bytes会触发错误解析,必然生成乱码。 - 字体配置失效:你提到更换了OpenSans字体,但大概率没有完成TTF字体的正确注册,也没有在段落、表格样式中强制指定该字体。Reportlab内置的默认字体(Helvetica、Times Roman等)仅支持基础ASCII字符,完全不包含č、ć、ž、š、đ这类东欧拉丁字符的字形,就算内容传入正确也会显示乱码/方块。

可直接落地的修复方案
按以下步骤调整代码即可解决问题:
- 正确注册支持扩展拉丁字符的TTF字体
不要依赖Reportlab内置的标准字体,提前将你准备好的OpenSans(推荐使用完整版本,或替换为Noto Sans Latin Extended,字符覆盖更稳定)通过TTFont模块注册,同时配置字体族避免加粗/斜体样式回退到默认字体:from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfbase.pdfmetrics import registerFontFamily # 替换为本地字体文件的实际存储路径 pdfmetrics.registerFont(TTFont('OpenSans', 'OpenSans-Regular.ttf')) pdfmetrics.registerFont(TTFont('OpenSans-Bold', 'OpenSans-Bold.ttf')) pdfmetrics.registerFont(TTFont('OpenSans-Italic', 'OpenSans-Italic.ttf')) pdfmetrics.registerFont(TTFont('OpenSans-BoldItalic', 'OpenSans-BoldItalic.ttf')) # 注册字体族映射,保证样式切换时不回退 registerFontFamily( 'OpenSans', normal='OpenSans', bold='OpenSans-Bold', italic='OpenSans-Italic', boldItalic='OpenSans-BoldItalic' ) - 修正段落样式,强制指定已注册的字体
你使用的styleN段落样式必须显式指定fontName为注册时的字体名,注意名称大小写敏感,必须完全匹配:from reportlab.lib.styles import ParagraphStyle styleN = ParagraphStyle( 'normal', fontName='OpenSans', # 核心配置,不能遗漏 fontSize=9, leading=11, # 行高可根据需求调整 # 保留你原本配置的其他样式参数即可 ) - 删除冗余编码逻辑,直接传入原生字符串
你代码中判断字符是否为ASCII、单独做encode的逻辑完全多余,Python3中字符串默认是Unicode编码,直接传入Paragraph即可,不需要任何手动转码:# 替换掉原来带encode判断的列表推导式 data2 = [[Paragraph(cell, styleN) for cell in row] for row in array] - 表格样式全局指定字体,避免局部回退
原TableStyle没有配置全局字体,需要补充FONTNAME规则,避免单元格内容自动回退到默认不支持特殊字符的字体:t = Table( data2, colWidths=[None] + [2.2*inch] + [1.3 * inch]*int(len(json.loads(request.POST['kolone'])) - 2 ), rowHeights= [None] + [0.5*inch] + [None] * int(len(array) -2), repeatRows=1 ) t.setStyle(TableStyle([ ('FONTNAME', (0,0), (-1,-1), 'OpenSans'), # 全局指定表格字体 ('TEXTCOLOR',(1,1),(-2,-2), "black"), ('FONTSIZE', (0,0),(-1,-1), 9), ('BOX', (0,0), (-1,0), 0.25, 'black'), ('PADDING', (0,0),(-1,-1), 2), ('VALIGN', (0,0), (-1,-1), 'TOP') ]))
避坑提示
- 任何情况下都不要给Reportlab的文本组件传入bytes类型内容,所有文本保持Python原生str类型即可,PDF生成时的编码工作由Reportlab内部自动完成,手动编码只会触发解析错误。
- 如果调整后仍有个别字符无法显示,检查你使用的字体文件是否为精简版,精简版字库常裁剪掉扩展拉丁区字符,替换为完整版字库即可。
- 注册字体时自定义的字体名(比如示例里的'OpenSans')要和所有样式里的fontName参数完全一致,拼写错误、大小写不匹配都会导致字体配置失效,自动回退到默认字体。
内容的提问来源于stack exchange,提问作者StrahinjaL
相关产品推荐
相关产品推荐

