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

相关推荐
十日十行15 小时前
Linux和window共享文件夹
linux
Sinclair19 小时前
简单几步,安卓手机秒变服务器,安装 CMS 程序
android·服务器
木心月转码ing1 天前
WSL+Cpp开发环境配置
linux
Rockbean2 天前
用40行代码搭建自己的无服务器OCR
服务器·python·deepseek
蝎子莱莱爱打怪2 天前
Centos7中一键安装K8s集群以及Rancher安装记录
运维·后端·kubernetes
茶杯梦轩2 天前
CompletableFuture 在 项目实战 中 创建异步任务 的核心优势及使用场景
服务器·后端·面试
崔小汤呀2 天前
最全的docker安装笔记,包含CentOS和Ubuntu
linux·后端
何中应2 天前
vi编辑器使用
linux·后端·操作系统
何中应2 天前
Linux进程无法被kill
linux·后端·操作系统
何中应2 天前
rm-rf /命令操作介绍
linux·后端·操作系统