Python调用WeasyPrint转PDF时图片无法渲染仅显示alt文本
WeasyPrint 本地资源加载失败问题解决方案
核心根因
渲染失败是两类规则限制叠加导致的:
- 直接写
C:/xxx/xxx格式的Windows盘符绝对路径,不符合file协议资源的标准URI格式。Chrome/Brave对这类路径做了特殊兼容豁免,Firefox、WeasyPrint默认严格遵守URI规范,会直接判定这类路径非法、拒绝加载资源 - 调用WeasyPrint加载HTML时如果不显式指定
base_url参数,库会以Python进程的当前工作目录为根解析所有资源路径,极易出现路径解析错位,触发资源拦截
分步排查解决
- 优先使用相对路径+显式base_dir配置,兼容性最高
整理项目目录结构,把HTML文件和所有依赖资源(SVG、PNG)放在统一项目根目录下,示例结构:
修改HTML内的资源引用为相对路径:project_root/ ├─ label.html ├─ assets/ │ ├─ LABEL_SVG.svg │ └─ qrcode.png
生成PDF时显式传入<img src="./assets/LABEL_SVG.svg" alt="SVG of Label" /> <div class="sn-number">3253343345</div> <img class="qr-code" src="./assets/qrcode.png" alt="qrcode" />base_url,指定资源解析的根目录,彻底避免路径错位:from weasyprint import HTML import os html_abs_path = os.path.abspath("path/to/your/label.html") project_root = os.path.dirname(html_abs_path) html = HTML(filename=html_abs_path, base_url=project_root) html.write_pdf("path/to/output/label.pdf") - 校验SVG文件格式兼容性
如果调整路径后PNG可以正常加载、SVG仍无法显示,逐一排查SVG本身的问题:- 确保SVG根标签携带标准命名空间属性:
<svg xmlns="http://www.w3.org/2000/svg" ...> - 把SVG内引用的外部字体、外部图片全部改成内联形式,不要依赖外部资源加载
- 删除SVG文件内多余的非标准自定义命名空间、脚本块,WeasyPrint不支持SVG内的JS执行
- 确保SVG根标签携带标准命名空间属性:
- 用Firefox做快速校验
调整完路径后直接用Firefox打开本地HTML文件,打开浏览器控制台看资源加载报错:如果Firefox可以正常加载所有图片,WeasyPrint可以正常渲染;如果仍加载失败,控制台的报错信息会明确标注是权限不足、路径错误还是资源格式非法,不需要反复调试PDF生成逻辑。 - 特殊场景备选方案:资源转base64内联
如果受部署环境限制无法使用相对路径,可以直接把所有图片、SVG转成base64编码嵌入HTML的src属性,完全绕开本地文件系统的加载限制:import base64 def get_base64_src(file_path: str, mime_type: str) -> str: with open(file_path, "rb") as f: b64_content = base64.b64encode(f.read()).decode("utf-8") return f"data:{mime_type};base64,{b64_content}" # 生成内联资源地址替换HTML内的src属性即可 svg_inline_src = get_base64_src("path/to/LABEL_SVG.svg", "image/svg+xml") qrcode_inline_src = get_base64_src("path/to/qrcode.png", "image/png")
注意:如果一定要用绝对路径,必须把Windows盘符路径转换成标准file协议URI格式,即
file:///C:/Users/xxx/xxx格式,不要直接写盘符开头的路径,否则非Chromium内核的工具/浏览器都会识别失败。
内容的提问来源于stack exchange,提问作者Twantie
相关产品推荐
相关产品推荐

