You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

python-pptx add_picture替换图片时descr被改为image.png问题求解

问题描述
  • 使用场景:通过python-pptx生成演示文稿后,会手动添加部分幻灯片,后续需要修改一张或多张图片时,希望重新运行程序可按相同文件名替换对应图片。
  • 故障现象:首次运行替换功能通常正常,替换后可保留原图片的descr属性,但多数情况下替换后图片descr会被自动设置为image.png,导致后续替换时无法定位目标图片。

最初编写的删图重插版替换函数:

def replace(self, newPic):
    for slide in self.pres.slides:
        for shape in slide.shapes:
            try:
                if shape._pic.nvPicPr.cNvPr.get('descr') == newPic:
                    top, left, width, height = shape.top, shape.left, shape.width, shape.height
                    self.deleteShape(shape)
                    img = slide.shapes.add_picture(self.inDir + "/" + newPic, left, top, width, height)
                    imgDescr = img._pic.nvPicPr.cNvPr.get('descr')
                   
            except AttributeError:
                pass

后续尝试的直接替换图片二进制方案运行时报错:

def replace(self, newPic):
    #If in list with every figure
    for slide in self.pres.slides:
        for shape in slide.shapes:
            try:
                if shape._pic.nvPicPr.cNvPr.get('descr') == newPic:
                    imgPic = shape._pic
                    imgRID = imgPic.xpath('./p:blipFill/a:blip/@r:embed')[0]
                    imgPart = shape.part.relatedpart(imgRID)

                    with open(self.inDir + "/" + newPic, 'rb') as f:
                        rImgBlob = f.read()

                    # replace
                    imgPart._blob = rImgBlob
            except AttributeError:
                pass

报错信息:

imgPart = shape.part.relatedpart(imgRID)
AttributeError: 'SlidePart' object has no attribute 'relatedpart'
解决方案

1. 二进制替换方案报错修复(优先推荐)

报错根因是方法名拼写错误:python-pptx中获取关联部件的方法是下划线分隔的related_part(),不是全小写连写的relatedpart。
该方案不需要删除原有形状重新插入,可完整保留原图片的位置、尺寸、裁剪效果、动画、层级、样式等所有属性,也不会自动修改descr属性,稳定性远高于删图重插方案。

修正后的代码:

def replace(self, newPic):
    for slide in self.pres.slides:
        for shape in slide.shapes:
            try:
                if shape._pic.nvPicPr.cNvPr.get('descr') == newPic:
                    imgPic = shape._pic
                    imgRID = imgPic.xpath('./p:blipFill/a:blip/@r:embed')[0]
                    # 修正方法名拼写
                    imgPart = shape.part.related_part(imgRID)

                    with open(f"{self.inDir}/{newPic}", 'rb') as f:
                        rImgBlob = f.read()

                    # 替换二进制内容
                    imgPart._blob = rImgBlob
            except AttributeError:
                pass

注意事项:

  • 如果新图片和原图片格式不一致(比如原PNG替换为JPG),需要同步修改图片部件的Content-Type,否则PPT打开会报错,可在替换blob后添加对应逻辑:
    # 例:替换为jpg格式时设置
    imgPart.content_type = "image/jpeg"
    # 替换为png格式时设置
    # imgPart.content_type = "image/png"
    

2. 删图重插方案修复

如果坚持使用删图重插逻辑,故障原因是插入新图片后没有手动设置descr属性,python-pptx会自动给新插入的图片descr赋值为默认文件名,很容易出现匹配值丢失的问题。需要在add_picture后手动给descr赋值为目标匹配值:

def replace(self, newPic):
    for slide in self.pres.slides:
        for shape in slide.shapes:
            try:
                if shape._pic.nvPicPr.cNvPr.get('descr') == newPic:
                    top, left, width, height = shape.top, shape.left, shape.width, shape.height
                    self.deleteShape(shape)
                    img = slide.shapes.add_picture(f"{self.inDir}/{newPic}", left, top, width, height)
                    # 手动设置descr属性,不要依赖默认值
                    img._pic.nvPicPr.cNvPr.set('descr', newPic)
            except AttributeError:
                pass

内容的提问来源于stack exchange,提问作者Selfors

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 20:27:15