大家好,我是程序员晚枫。
今天(2026 年 10 月 26 日)开源项目 python-office 上了 1.1.0。
这次更新最值得说的一件事:python-office 终于有命令行了。
完整官方文档(含中英文):https://www.python-office.com/about/v1.1.0-release
项目地址:https://github.com/CoderWanFeng/python-office
一句话总结这次更新
| 变更 | 内容 |
|---|---|
🆕 命令行 po | 7 大模块 42 个子命令,不写 Python 也能用 |
| 🆕 5 个 Excel 方法 | 差异比对、去重、列画像、转 JSON、转 CSV |
| ⚡ 懒加载优化 | import office 不再拖入整套依赖树 |
安装完直接就有:
1 | po --version |
为什么我要做这个命令行
python-office 从 2022 年发布到现在,收到的最多的一类反馈是:
「我不会写 Python,能不能不写代码就用?」
我的回答一直是「可以用 AI 帮你写」。但这有个前提:你得有个 Python 环境,得会打开终端,得能读懂报错。
这次我想试试另一条路:直接把能力做成命令,交给终端、交给脚本、交给 AI Agent。
安装 python-office 之后,po 这个命令就在你终端里了:
1 | # 合并 PDF |
完整命令树(7 模块 42 个子命令):
1 | po |
每个命令都能自己查帮助:
1 | po --help # 全部 7 个模块 |
这次最被低估的设计:--json
说实话,做这个命令行时,我一开始以为大家会用 po pdf merge2pdf 这种直接调用。
但做完之后我越来越觉得,真正值钱的不是命令本身,是 --json。
1 | po --json tools url2ip www.python-office.com |
输出只有一行:
1 | {"ok": true, "result": "1.2.3.4"} |
出错也是一行,退出码 1:
1 | {"ok": false, "error": "FileNotFoundError: [Errno 2] No such file or directory: 'a.pdf'"} |
一个容易漏掉的坑
python-office 内部的库函数会自己 print(进度条之类的)。如果不处理,输出就会变成这样:
1 | rows: 100%|██████████| 5/5 |
脚本解析直接崩。
po 的处理办法是:库内部输出全部丢到 stderr,stdout 只留那一行 JSON。
1 | stdout: {"ok": true, "result": null} ← 只有这一行 |
这个边界很多项目会漏,但它是「命令行能不能被脚本可靠调用」的分水岭。
为什么这对 AI Agent 特别重要
现在的 AI Agent(Claude Code、Cursor、Codex)跑命令时,最怕输出不结构化。要么解析失败,要么把进度条当成结果。
po --json 天然就是给 Agent 用的:
| Agent 的需求 | po --json 怎么满足 |
|---|---|
| 判断成功还是失败 | 看 ok 字段,不用去猜错误文本 |
| 拿结果 | 看 result 字段 |
| 知道为什么错 | 看 error 字段 |
| 判断要不要继续 | 看退出码(成功 0 / 失败 1) |
所以现在 python-office 的 81 个 Skill,都有了统一的命令行入口。
你要是正在搭 Agent 工作流,这条是真能用的。
另一个大改进:import office 变快了
这个改动用户可能感觉不到,但它影响很大。
改之前
1 | import office |
这一行会把全部 14 个 API 模块的依赖树一起拖进来。poexcel、popdf、povideo、poocr、pospider 全都加载。
你只想处理 PDF,但得把一整套都装上、全都启动一遍。
改之后
Python 3.7 以上走 PEP 562,改成按需加载:
1 | import office # 此时不加载任何 po* 子库 |
我本地实测(Python 3.12):
1 | import office 之后加载的 po* 模块:[] ← 空的 |
实际收益
| 收益 | 说明 |
|---|---|
| 安装体积 | 只用 PDF 的用户不用装 povideo / poocr / pospider 这类重包 |
| 启动速度 | import office 不再是「等半天」 |
| Docker 镜像 | 核心 CLI 镜像只要 8 个子库;全量依赖里有 moviepy、paddleocr,装一次好几分钟 |
| 兼容性 | Python 3.6 没 PEP 562,自动回退老逻辑,行为不变 |
一个我要提醒你的副作用
office/__init__.py 里不再有真实的 from office.api import ... 语句了。
这意味着你 IDE 里的「跳转定义」和自动补全会退化。
如果你平时在 VS Code / PyCharm 里靠 office.pdf 补全提示,升级后可能会发现跳转不灵了。
这是这次改造的隐性代价,我在合入 PR 时专门写在了评审意见里,也留了退路。如果社区反馈太影响体验,可以把懒加载下沉到 office/cli/ 内部,office/__init__.py 保持原样。
升级之后建议先验证一下你的 IDE。
顺手补齐的 5 个 Excel 方法
这次另一个贡献者 my12yyds 补齐了「表格处理」链条里缺的一环。
之前的方法主要解决格式转换与合并,这次补上的是比对、去重、质量统计:
| 方法 | 作用 | 和老方法的区别 |
|---|---|---|
excel_diff | 比对两份 Excel | merge2excel 是合并,这个是找差异 |
excel_dedupe | 按列或整行去重 | 老方法没有重复检测能力 |
excel_column_stats | 逐列画像 | find_excel_data 按关键词找内容,这个按列做画像 |
excel2json | 工作表转 JSON | excel2markdown 输出给人看,这个输出给程序读 |
excel2csv | 导出 CSV | excel2pdf 输出 PDF,这个输出纯文本 |
全部只依赖 openpyxl,没引入任何新的第三方包。
excel_diff:主键配对这个设计很讲究
1 | from skills.excel import excel_diff |
只按行号比对有个致命问题:中间插一行,后面所有行都被标成差异。
按订单号、学号、工号这类唯一编号配对,行顺序变了也不产生噪音。
而且,主键重复或为空会直接报错,不会静默给你一份错的比对结论。
这个取舍很专业,评审时我专门点了出来。
excel2csv:默认 utf-8-sig 解决中文乱码
1 | from skills.excel import excel2csv |
默认编码是 utf-8-sig(带 BOM)。
这是中文用户最高频的坑:存成普通 UTF-8 再用 Excel 双击打开,乱码;加 BOM 就正常。
要给 Linux 工具链用的话,显式传 encoding='utf-8'。
excel_dedupe:返回明细而不是一个数字
1 | from skills.excel import excel_dedupe |
排查问题的时候你需要知道「第 5 行和第 2 行重复」,光给个 duplicate_count 是没法用的。
⚠️ 一个要说清楚的事:这 6 个贡献者 Skill(
batch_rename_by_excel+ 上面 5 个)的实现代码在仓库的contributors/目录,这个目录不随 pip 安装包一起发布。从 PyPI 装完调用它们,会得到一条很明确的 ImportError 提示,让你克隆源码仓库或直接复制文件过去用。这是贡献隔离模式的固有限制,不是 bug。
顺便说说这次的协作过程
1.1.0 的功能全部来自社区贡献者。两个 PR 的过程里,有几个点我觉得挺值得记录。
PR #184:CLI 的设计取舍
贡献者 Edwin.JH.Lee 提的第一波 CLI,用的是分波推进:本波先跑通 7 个核心模块 42 个子命令,其余的(video / web / word / ppt / wechat 共 20 个命令)后面补。
因为注册表结构已经就位,加命令只是加数据条目。
贡献者自建的测试基建,是这个 PR 最有价值的部分
| 测试层 | 数量 | 说明 |
|---|---|---|
pytest tests/test_code/test_cli.py | 37 passed | 内置 po* stub,不装重型依赖也能跑 CI |
.x-cmd/test.sh real 模式 | 15/15 | 真转换 + 产物校验(txt2pdf→merge2pdf 页数、excel2markdown 表格、url2ip 真实 DNS) |
.x-cmd/test.sh stub 模式 | 10/10 | 零依赖环境自动回退 |
还附了一个 python:3.10-slim 的 Docker 镜像,apt 和 pip 都走 aliyun 镜像。
这里有个细节我要夸:他专门写了一条用例,验证「库函数自己 print 时 stdout 仍然干净」。这个边界很多项目会漏。
评审意见里最值得留档的一条
关于 PEP 562 懒加载,我在合入评论里留了个保留意见:
这个改造的收益是实打实的——
import office不再拖入 poexcel/popdf/povideo 这类重型依赖树,对 CLI 启动速度和安装体积都有帮助。但它有一个隐性代价:__init__.py里不再有真实的from office.api import ...语句,IDE 的「跳转定义」「自动补全」会退化。
处理方式是先按贡献者的方案合入,把代价记在评论里,同时给出退路:如果社区反馈跳转体验下降,可以把懒加载下沉到 office/cli/ 内部,core 目录保持原样。
PR #185:贡献者自己补上了上次的漏
#183 合入的时候,我发现贡献者加了 skills/file/batch_rename_by_excel/ 目录,但没在父包 skills/file/__init__.py 里注册。结果 from skills.file import batch_rename_by_excel 会报 ImportError,跟同目录其他 Skill 的导出方式不一致。
我补了一个 chore(skills) 提交完成注册,评论里也说了「如果你希望这条注册由你自己提交,可以把这个提交 revert 掉重提」。
到了 #185,贡献者主动在父包 skills/excel/__init__.py 注册了,而且严格只在末尾追加、不动既有行。
上次漏掉的那一步,这次他自己补上了。这种「上一轮的反馈被认真吸收」,比代码本身更让我觉得社区在往好的方向走。
一个连续踩了三次的坑
#183 和 #185 的 6 个 Skill 都用了 try/except 兜底,处理「contributors/ 目录不随包发布」的情况。但写法有问题:
1 | except ImportError as _import_error: |
Python 3 在 except 块结束后会自动 del 掉 as 绑定的异常名,闭包里引用的 _import_error 就成了未定义名字。
真实 pip 安装环境(contributors 目录不存在)下调用,实际抛出的是:
1 | NameError: name '_import_error' is not defined |
而不是作者预期的、带着明确指引的 ImportError。
修复方式是把异常存到模块级变量:
1 | except ImportError as _import_error: |
回归测试新增在 tests/test_code/test_contributors_skill_fallback.py,显式 mock 掉 contributors 导入来触发兜底分支。
这个分支在源码仓库里永远不会自然触发,所以常规测试根本抓不到。把修复回退后,新测试的 12 个 subtest 全部失败。
一条项目级的规矩
从 #181 / #182 的处理能看出来,python-office 现在的规矩是:改动 office/ 等核心目录的贡献,需要先开 issue 讨论,不能直接提 PR。 隔离式贡献(contributors/ 目录 + skills/ 包装)的可以直接提。
这条规矩的价值是:核心目录不会被「顺手改一下」的 PR 反复扰动,同时新贡献者也不用担心一不小心改坏主线。
怎么升级
1 | pip install python-office --upgrade |
国内网络建议走镜像:
1 | pip install -i https://mirrors.aliyun.com/pypi/simple python-office --upgrade |
验证一下:
1 | po --version |
只想用 CLI 不想要全套依赖的话:
1 | pip install python-office popdf poexcel poimage pofile wftools pomarkdown |
所有用法速查
| 用法 | 场景 | 示例 |
|---|---|---|
po 命令 | 终端里直接干活 | po pdf merge2pdf a.pdf b.pdf |
po --json | 脚本 / CI / AI Agent 调用 | po --json tools url2ip example.com |
python -m office | 等价入口 | python -m office --help |
from skills.X import Y | 现有 Python 用法 | from skills.pdf import pdf2docx |
import office | 现有 Python 用法 | office.pdf.pdf2docx() |
最后
python-office 从 2022 年发布到现在四年,这次是第一次真正的大改。
一个 Python 库,现在多了命令行,也多了被 Agent 直接调用的入口。
功能上它还是那个一句话搞定的 python-office,能触达的人变多了。
如果你想一起参与:
- 🐛 报告 Bug:https://github.com/CoderWanFeng/python-office/issues
- 💡 提功能:https://github.com/CoderWanFeng/python-office/discussions
- 📝 改文档:直接提 PR
我一般下午 merge 一次。
参考链接
- python-office 官方文档站:https://www.python-office.com
- python-office 1.1.0 完整发布说明:https://www.python-office.com/about/v1.1.0-release
- python-office GitHub 仓库:https://github.com/CoderWanFeng/python-office
- python-office PyPI 包:https://pypi.org/project/python-office/
- PR #184 feat(cli): 第一波 CLI 实现 —— po 命令:https://github.com/CoderWanFeng/python-office/pull/184
- PR #185 feat(contributors): 新增 5 个 Excel 数据核对与整理方法:https://github.com/CoderWanFeng/python-office/pull/185
相关阅读
🎓 AI 编程实战课程
程序员晚枫专注AI编程培训,通过 《50讲 · AI编程训练营》,让小白也能用AI做出实际项目。帮你从零上手!
- 👉 免费试看:网盘链接,免费试看前3讲,先看看适不适合自己
- 👉 - 👉 课程报名:点击这里报名,现在报名还送书📖




