PPTX数据格式的更换图片

2) 推荐且兼容的实现(最终代码

下面函数不依赖 ImagePart.from_blob,使用 Image.from_blob + ImagePart.new,并且包含完整断点输出 (你可以在这些处下断点或查看日志),以及安全删除旧关系 的逻辑(避免直接 ._rels.pop 导致 package 被污染)。

把它直接拷到你的项目里运行(记得把路径改成你本地的):

复制代码

import os from pptx.opc.constants import RELATIONSHIP_TYPE as RT from pptx.oxml.ns import qn # 这两个类来自 python-pptx from pptx.parts.image import Image as PPTXImage from pptx.parts.image import ImagePart def replace_image_robust(shape, slide_part, image_source, content_type_hint=None): """ Robust image replace: - image_source: 文件路径 (str) 或 bytes - 不依赖 ImagePart.from_blob;使用 Image.from_blob + ImagePart.new - 在关键点打印调试信息(可断点) - 安全地 relate_to(new ImagePart), 更新 blip, 并 drop_rel(old_rId) """ print("\n===== replace_image_robust 开始 =====") # 1) 读取 image blob / 构建 pptx Image 对象 if isinstance(image_source, str): if not os.path.exists(image_source): raise FileNotFoundError(image_source) with open(image_source, "rb") as f: blob = f.read() filename = os.path.basename(image_source) elif isinstance(image_source, (bytes, bytearray)): blob = bytes(image_source) filename = None else: raise TypeError("image_source must be path or bytes") # 创建 pptx.parts.image.Image(通用) img_obj = PPTXImage.from_blob(blob, filename) # DEBUG 断点 A: 检查 image meta print("DBG A: image filename:", getattr(img_obj, "filename", None)) print("DBG A: image content_type:", getattr(img_obj, "content_type", None)) # 2) 用 ImagePart.new(package, image) 构造合法 ImagePart package = slide_part.package image_part = ImagePart.new(package, img_obj) # DEBUG 断点 B: 检查 image_part print("DBG B: image_part type:", type(image_part)) print("DBG B: image_part.partname:", image_part.partname) print("DBG B: image_part.content_type:", getattr(image_part, "content_type", None)) # 3) 把 image_part 关联到 slide_part,得到 new rId new_rId = slide_part.relate_to(image_part, RT.IMAGE) print("DBG C: new_rId:", new_rId) # 4) 更新 shape 的 blip/embed 指向 new rId blips = shape.xpath(".//a:blip") if not blips: raise RuntimeError("can't find <a:blip> inside shape") blip = blips[0] old_rId = blip.get(qn("r:embed")) blip.set(qn("r:embed"), new_rId) print(f"DBG D: old_rId -> new_rId: {old_rId} -> {new_rId}") # 5) 在删除 old rId 前做一次安全检查(不要直接 pop 私有 dict) try: old_rel = slide_part.rels.get(old_rId) except Exception: old_rel = None if old_rel is not None and hasattr(old_rel, "target_part"): # 安全删除 slide_part.drop_rel(old_rId) print("DBG E: dropped old rId:", old_rId) else: print("DBG E: skip dropping old_rId (not found or invalid):", old_rId) # 6) 再打印 slide_part.rels._rels(安全遍历,标出非 str key / 非 _Relationship value) print("\nDBG F: slide_part.rels._rels snapshot:") for k, v in getattr(slide_part.rels, "_rels", {}).items(): k_repr = k if isinstance(k, str) else f"<non-str key {type(k)}>" v_type = type(v) target_part_type = type(getattr(v, "target_part", None)) if v is not None else None print(f" key={k_repr}, rel_type={v_type}, target_part={target_part_type}") print("===== replace_image_robust 结束 =====\n") return new_rId

相关推荐
M78佐菲3 小时前
Linux学习笔记:TCP协议
linux·笔记·学习·tcp/ip·算法
Brilliantwxx3 小时前
【Linux】 进程(9)程序与进程地址空间(基础+进阶+面试题)
linux·运维·服务器·开发语言·c++
不怕犯错,就怕不做3 小时前
git prune 自动删除本地记录中那些远程已经不存在的分支引用
linux·服务器·git
richdata4 小时前
商品数字化不是先做大数据,而是先把数据变成可用决策
大数据·运维·数据治理·商品数字化·智能补货·ai商品决策
weixin_416667964 小时前
【无标题】
运维·服务器·网络
一池秋_5 小时前
arm低配linux设备,桌面应用冷启动提速方法
linux·运维·arm开发
惜离殇5 小时前
从零开始的敲代码生活--Linux应用软件(文件操作基础1)
linux·c语言·文件操作·标准io
上海云盾-小余7 小时前
流量攻击复盘:为什么 WAF 完好,业务依旧瘫痪
运维·服务器·网络
IT大白鼠7 小时前
Docker 私有仓库管理:Harbor 企业级仓库搭建与镜像全生命周期管理
运维·docker·容器
戴西软件7 小时前
戴西iDWS.3DViz Suite数据轻量化可视化软件,从传统桌面软件向云端协同的重大突破
大数据·运维·网络·人工智能·机器学习·3d