news 2026/10/12 3:26:56

python-docx 形状 API 详解:InlineShapes 集合与 InlineShape 内联形状的访问与尺寸操作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
python-docx 形状 API 详解:InlineShapes 集合与 InlineShape 内联形状的访问与尺寸操作
  • 后端

【免费下载链接】python-docx

Create and modify Word documents with Python

项目地址:https://gitcode.com/gh_mirrors/py/python-docx
点击查看免费下载

导读

在 python-docx 中,图片、图表等图形对象以“形状(shape)”的形式存在于文档的绘图层(drawing layer),其中随文字流排布的称为内联形状(inline shape)。本文以官方 API 文档 docs/api/shape.rst 为主线,深入讲解InlineShapes集合与InlineShape对象的用法:如何遍历、索引访问文档中的所有内联形状,如何读取与修改每个形状的显示尺寸,以及如何识别形状类型(图片、链接图片、图表、SmartArt)。读完本文,你将能够用几行代码完成对 Word 文档内联图片的枚举、查重、缩放等常见需求。

一、先理解概念:什么是内联形状

Word 文档在概念上分为两个层:文本层(text layer)与绘图层(drawing layer)。文本层中的对象按从左到右、从上到下的顺序流动排版,排满一页后自动换页;绘图层中的图形对象(即“形状”)则被放置在任意位置,这类形状也被称为“浮动形状(floating shape)”。

一张图片既可能出现在文本层,也可能出现在绘图层。出现在文本层时,它被称为内联形状(inline shape),更具体地说,是内联图片(inline picture)。内联形状被当作一个“大字符”(字符字形,character glyph)处理:

  • 行高会被拉高以容纳该形状;
  • 形状会像文字一样换行,宽度放不下的行会被折到下一行;
  • 在其前面插入文本,会把它向右“推”走。

通常图片会单独占一个段落,但这并非强制——它所在的段落前后完全可以有文字。相关概念背景可参考 docs/user/shapes.rst。

从 XML 结构看,内联形状表现为w:r(run)下的<w:drawing>子元素,其中承载一个<wp:inline>元素(DrawingML 内联对象容器)。<wp:inline>内部依次包含表示显示尺寸的<wp:extent>、非可视属性<wp:docPr>以及承载具体图形对象(如pic:pic图片)的<a:graphic>/<a:graphicData>,可参考 docs/dev/analysis/features/shapes/shapes-inline.rst 中的最小 XML 与完整标本 XML。

二、InlineShapes:文档内联形状的集合对象

InlineShapes(位于docx.shape模块)是当前文档中全部InlineShape实例组成的序列(Sequence),支持len()、迭代和索引访问三种标准操作。官方 API 文档将其成员排除add_picture后完整导出(即当前公开能力为序列访问),实现见 src/docx/shape.py。

2.1 获取集合

InlineShapes集合通过Document.inline_shapes属性获得,这是最常用的入口:

from docx import Document document = Document("having-images.docx") inline_shapes = document.inline_shapes

其实现位于 src/docx/document.py,实际委托给文档部件(StoryPart)的inline_shapes属性。

2.2 三种访问方式

# 1. 数量 count = len(inline_shapes) # 2. 迭代 for shape in inline_shapes: print(shape.type, shape.width, shape.height) # 3. 索引访问 first_shape = inline_shapes[0]

底层机制:InlineShapes在构造时接收文档的CT_Body元素,并通过 XPath 表达式"//w:p/w:r/w:drawing/wp:inline"定位全部内联形状(见 src/docx/shape.py)。也就是说,集合遍历的是文档正文中所有段落 run 内的wp:inline元素,每个元素被包装为一个InlineShape代理对象。索引越界时会抛出带明确信息的IndexError,例如"inline shape index [3] out of range"。

2.3 集合行为的测试证据

单元测试 tests/test_shape.py 覆盖了上述行为:

  • len(inline_shapes)返回集合内形状数量;
  • 迭代产生的每个元素都是InlineShape实例;
  • inline_shapes[idx]支持负索引与正索引,越界抛出IndexError。

Behave 特性文件 features/shp-inline-shape-access.feature 也验证了“长度为 5、可迭代、可按索引访问”的完整场景,其步骤实现见 features/steps/shape.py。

三、InlineShape 对象:尺寸读取与修改

InlineShape是对单个<wp:inline>元素的代理对象(见 src/docx/shape.py),公开三个成员:height、type、width,这正是 API 文档autoclass指令中列出的全部成员。

3.1 width 与 height:Length 类型的显示尺寸

width和height返回该内联形状的显示尺寸(display width / display height),单位是EMU(English Metric Units,英文公制单位),返回值是Length的实例:

>>> inline_shape.height 914400 >>> inline_shape.height.inches 1.0

这正是官方 API 文档给出的示例:914400 EMU 恰好等于 1 英寸。Length继承自int,所以它可以像普通整数一样参与算术比较(如inline_shape.width == 1778000);同时它自带一套只读的单位换算属性,见下表(实现于 src/docx/shared.py):

属性含义换算系数(EMU 数量)返回类型
emu英文公制单位1int
inches英寸914,400 / inchfloat
cm厘米360,000 / cmfloat
mm毫米36,000 / mmfloat
pt磅(point)12,700 / ptfloat
twips缇(二十分之一磅)635 / twipint

Length还提供了配套的便捷构造函数:Inches(0.5)、Cm(12)、Mm(240.5)、Pt(...)、Twips(...)、Emu(457200)等(见 src/docx/shared.py),赋值时可以直接使用它们:

from docx.shared import Inches, Cm, Emu inline_shape.width = Inches(1.75) inline_shape.height = Cm(3)

3.2 修改尺寸的底层机制:两处同时写入

width和height都是可读写的(read/write)属性。有意思的是,源码显示赋值时并非只改一处:height的 setter 同时更新wp:inline/wp:extent的cy属性和pic:spPr/a:xfrm/a:ext的cy属性(见 src/docx/shape.py),width同理更新两处cx。

原因在开发分析文档 docs/dev/analysis/features/shapes/shapes-inline-size.rst 中有说明:内联形状的位置完全由与其同行的文本决定,但尺寸可以显式指定。对于图片这类形状,容器(wp:extent)的尺寸决定显示大小,而pic元素内的尺寸记录图片的原始大小;两者共同维护,才能保证 Word 中显示的缩放比例正确。特性文件 features/shp-inline-shape-size.feature 与步骤实现 features/steps/shape.py 验证了“查询已知尺寸”和“修改为Inches(1) × Inches(0.5)后两处属性同步更新”的行为,单元测试 tests/test_shape.py 则直接断言修改后整个wp:inline的 XML 中两处extent均变为新值。

四、type 属性:识别内联形状的类型

InlineShape.type是只读属性,返回docx.enum.shape.WD_INLINE_SHAPE枚举的一个成员,用于区分内联形状的种类:

>>> inline_shape.type WD_INLINE_SHAPE.PICTURE

4.1 支持的枚举成员

WD_INLINE_SHAPE(即WD_INLINE_SHAPE_TYPE,见 src/docx/enum/shape.py)对应 Word VBA 的WdInlineShapeType枚举,本仓库定义如下:

枚举成员数值含义
WD_INLINE_SHAPE.PICTURE3嵌入式图片
WD_INLINE_SHAPE.LINKED_PICTURE4链接式图片
WD_INLINE_SHAPE.CHART12图表
WD_INLINE_SHAPE.SMART_ART15SmartArt 图形
WD_INLINE_SHAPE.NOT_IMPLEMENTED-6暂未实现的形状类型

4.2 type 的判定逻辑

源码中的判定依据是graphicData元素的uri命名空间(见 src/docx/shape.py):

  • uri为pic命名空间(http://schemas.openxmlformats.org/drawingml/2006/picture)时:检查pic:blipFill/a:blip元素——存在r:link属性(引用外部图片)则判为LINKED_PICTURE,否则判为PICTURE(存在r:embed表示图片部件已嵌入文档);
  • uri为c命名空间(chart)时判为CHART;
  • uri为dgm命名空间(diagram)时判为SMART_ART;
  • 其余未知 URI 一律返回NOT_IMPLEMENTED。

三个命名空间常量定义于 src/docx/oxml/ns.py。值得注意的边界情况:当a:blip同时带r:embed和r:link(既嵌入又链接,虽不常见)时,源码优先返回LINKED_PICTURE;该行为同样被单元测试覆盖(见 tests/test_shape.py),并在 features/shp-inline-shape-access.feature 的场景大纲中列为显式用例。

4.3 典型应用:按类型筛选图片

from docx.enum.shape import WD_INLINE_SHAPE embedded = [ s for s in document.inline_shapes if s.type == WD_INLINE_SHAPE.PICTURE ] print(f"文档中共有 {len(embedded)} 张嵌入图片")

五、如何产生内联形状:add_picture 入口

理解集合与单个形状之后,再看形状从何而来。python-docx 当前主要支持的是内联图片(浮动图片暂未开放添加)。两个常用入口:

5.1 Document.add_picture:文档末尾追加

document.add_picture("python-icon.png", width=Inches(1.0))

该方法在文档末尾新建一个独立段落,并在其中添加含图片的 run(见 src/docx/document.py)。尺寸规则:

  • width、height都不给 → 以图片原始尺寸显示;
  • 只给其一 → 以该值计算缩放系数,等比缩放另一维,保持宽高比;
  • 原始尺寸依据图片文件中的dpi 值计算,文件未声明 dpi 时按默认 72 dpi 处理(这在 JPEG 等格式中很常见)。

5.2 Run.add_picture:在指定位置插入

paragraph = document.add_paragraph("图片前方文字:") run = paragraph.add_run() run.add_picture("python-powered.png", height=Cm(2.0)) paragraph.add_run(",图片后方文字")

Run.add_picture把内联图片插入到该 run 末尾,从而支持“文字 + 图片 + 文字”的混合排版(见 src/docx/text/run.py)。其底层调用链为:StoryPart.new_pic_inline()负责将图片加入文档部件、计算缩放后的cx/cy、生成全局唯一的形状 id,最终由CT_Inline.new_pic_inline()组装<wp:inline>元素(见 src/docx/parts/story.py 与 src/docx/oxml/shape.py)。形状 id 通过扫描文档中全部@id属性取最大值加 1 得到,保证文档内唯一(见 src/docx/parts/story.py)。add_picture会返回InlineShape对象,因此可以链式调整尺寸:

shape = document.add_picture("mountain.bmp") shape.width = Inches(3.5) shape.height = Inches(2.0)

六、完整实战:统计并统一缩放文档内所有图片

将上述 API 组合起来,可以实现一个常见的批处理任务——枚举文档全部内联图片并统一宽度:

from docx import Document from docx.enum.shape import WD_INLINE_SHAPE from docx.shared import Inches document = Document("report.docx") for shape in document.inline_shapes: if shape.type != WD_INLINE_SHAPE.PICTURE: continue # 读取当前尺寸(EMU 整数,可直接比较) print(f"原尺寸:{shape.width} x {shape.height} EMU") print(f"即 {shape.width.inches:.2f} x {shape.height.inches:.2f} 英寸") # 统一缩放到 4 英寸宽,高度按同比例(由 Word 依据 spPr 中的原始尺寸换算) shape.width = Inches(4) document.save("report-resized.docx")

注意:width/height读取到的 EMU 是显示尺寸;修改只影响显示大小,不会改变图片部件本身的像素数据,因此该操作可以放心重复执行。

七、小结与延伸阅读

本文围绕官方 API 文档 docs/api/shape.rst 展开:InlineShapes集合支持len()、迭代、索引访问,InlineShape提供可读写的width/height(Length类型,内置 EMU 与英寸、厘米、毫米、磅、缇的换算)以及只读的type(WD_INLINE_SHAPE枚举,可区分嵌入图片、链接图片、图表与 SmartArt)。结合源码可以看到,尺寸修改会同步更新wp:extent与pic:spPr两处 XML 属性,类型判定则基于graphicData的命名空间 URI。

如需继续深入,可参考:

  • 集合与单形状的单元测试:tests/test_shape.py
  • Behave 行为驱动用例:features/shp-inline-shape-access.feature、features/shp-inline-shape-size.feature 及其步骤实现 features/steps/shape.py
  • Length类的完整定义与全部单位构造函数:src/docx/shared.py
  • wp:inline的 XML 结构、最小 XML 与 XSD schema 定义:docs/dev/analysis/features/shapes/shapes-inline.rst、docs/dev/analysis/features/shapes/shapes-inline-size.rst
  • 图片内联容器pic:pic的 XML 细节:docs/dev/analysis/features/shapes/picture.rst
  • 文本层/绘图层概念:docs/user/shapes.rst
  • 后端

【免费下载链接】python-docx

Create and modify Word documents with Python

项目地址:https://gitcode.com/gh_mirrors/py/python-docx
点击查看免费下载

相关推荐

上一篇:【亲测免费】 HAPI FHIR 快速入门指南
下一篇:Task构建工具:现代开发工作流的终极自动化指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 3:23:01

虚拟电厂日前日内双时间尺度调度:Matlab+Yalmip建模详解

这两年做虚拟电厂&#xff08;VPP&#xff09;优化调度&#xff0c;我前前后后复现过不少公开论文里的模型&#xff0c;最实用、落地价值最高的仍然是“日前调度 日内调度”这套双时间尺度框架。网上流传的版本很多&#xff0c;但真正把两层逻辑讲清楚、代码能直接跑通的却不多…

作者头像 李华
网站建设 2026/10/12 3:22:52

remocn一次性讲透27种Remotion场景转场:从硬切到Shader擦除

【免费下载链接】remocn Production-ready animations, transitions, backgrounds, and scenes for Remotion 项目地址&#xff1a; https://gitcode.com/gh_mirrors/re/remocn 点击查看 免费下载 remocn 是一个面向 Remotion 的复制粘贴式动效组件库&#xff0c;它的 Transit…

作者头像 李华
网站建设 2026/10/12 3:20:46

mysql获取分组中的指定数据(附四大排序函数说明)

目录一.背景二.解决方案1.先排序后分组方式2.利用rank() over...&#xff08;推荐&#xff09;3 mysql四大排名函数&#xff08;1&#xff09;排序条件下的排名&#xff08;2&#xff09;分区排序条件下的排名一.背景 &#xff1a; 举个例子&#xff0c;现有两张表分别是老师和…

作者头像 李华
网站建设 2026/10/12 3:20:42

CubeFS 中的 HttpRouter 深入解析:Go 高性能 HTTP 路由器的原理与实战

存储分布式文件系统对象存储云原生 【免费下载链接】cubefs cloud-native distributed storage 项目地址&#xff1a; https://gitcode.com/gh_mirrors/cu/cubefs 点击查看 免费下载 HttpRouter 是一个基于压缩字典树&#xff08;Radix Tree&#xff09;实现的高性能 Go HTTP …

作者头像 李华
网站建设 2026/10/12 3:20:31

无线路由器当无线AP用:网线插LAN口,手把手配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华