- 后端
【免费下载链接】python-docx
Create and modify Word documents with Python
导读
在 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 | 英文公制单位 | 1 | int |
inches | 英寸 | 914,400 / inch | float |
cm | 厘米 | 360,000 / cm | float |
mm | 毫米 | 36,000 / mm | float |
pt | 磅(point) | 12,700 / pt | float |
twips | 缇(二十分之一磅) | 635 / twip | int |
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.PICTURE4.1 支持的枚举成员
WD_INLINE_SHAPE(即WD_INLINE_SHAPE_TYPE,见 src/docx/enum/shape.py)对应 Word VBA 的WdInlineShapeType枚举,本仓库定义如下:
| 枚举成员 | 数值 | 含义 |
|---|---|---|
WD_INLINE_SHAPE.PICTURE | 3 | 嵌入式图片 |
WD_INLINE_SHAPE.LINKED_PICTURE | 4 | 链接式图片 |
WD_INLINE_SHAPE.CHART | 12 | 图表 |
WD_INLINE_SHAPE.SMART_ART | 15 | SmartArt 图形 |
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.pywp: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
相关推荐
Ant Design Avatar 头像尺寸与形状全解析:三种尺寸、两种形状的源码级实战指南
Ant Design Avatar 头像尺寸与形状全解析:三种尺寸、两种形状的源码级实战指南 本篇以 Ant Design 组件库中 Avatar(头像)组件的
前端UI组件设计系统YOLOv6 训练尺寸模式详解:正方形训练、矩形训练与固定尺寸输入的原理与实操
YOLOv6 训练尺寸模式详解:正方形训练、矩形训练与固定尺寸输入的原理与实操 YOLOv6 通过 img size 、 rect 、 specific sha
人工智能深度学习计算机视觉预训练模型量化Invoke-AtomicRedTeam跨平台指南:在Windows、Linux和macOS上的部署与使用终极教程
Invoke AtomicRedTeam跨平台指南:在Windows、Linux和macOS上的部署与使用终极教程 🔍 Invoke AtomicRedTea
网络安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考