> 备选标题(发布时挑一个):
> 1. 我用 Python 写了个三栏式笔记本,单文件 exe、数据 100% 本地、还能导入笔记软件导出的 PDF
> 2. 放弃云笔记:一个 PySide6 打造的便携本地笔记本(笔记 PDF 一键迁移 + 富文本 + 全文检索)
> 3. Python + Qt 打造生产力工具:WorkNotes 本地笔记全记录(含 7 个踩坑实录)
配图说明 :文中图片位于 WorkNotes\shots\blog_assets\,上传 CSDN 时把 Markdown 里的图片路径替换为 CSDN 相册图即可(直接把 png 拖进 CSDN 编辑器)。截图全部使用合成演示数据,不含任何真实笔记内容。
一、为什么要自己写一个笔记软件
用了很多年云笔记软件,两个痛点始终无解:
- 数据在云端:公司内网和涉密环境用不了;换设备同步全凭运气。
- 导出困难:导出 PDF 后格式四散(分区信息全丢),想把多年工作笔记迁走几乎不可能。
于是用 PySide6 写了 WorkNotes ------一个绿色免安装、数据 100% 本地、经典三栏结构 (分区 → 页面 → 富文本)的笔记 exe,并专门做了笔记软件导出 PDF 的自动还原导入。

二、功能总览
2.1 经典三栏结构 + 可切换布局
左侧分区 (彩色标签,可改色、可排序)→ 中间页面列表 → 右侧富文本编辑器 。
分区支持 Ctrl+T 一键横排,切换为顶部标签条布局:

深色主题 Ctrl+L 一键切换:

2.2 富文本编辑(该有的都有)
- 字体、字号、颜色(16 色色板 + 最近使用)、荧光高亮、删除线、上下标
- 标题 1--5 级(Ctrl+1..5,Ctrl+0 回正文)
- 列表样式可选(●○▪、1. a. A. i. I.,列表上直接换样式)
- 段落对齐、缩进、代码块样式、插入表格、图片、水平线、日期
2.3 一键整理格式(个人最爱的功能)
写笔记时随手一记,格式难免乱。工具栏 "✨ 整理" 一键收拾:
- 命令行 → 等宽代码块(内置约 150 个常见命令识别,含中文行防误判)
- "xxx:"结尾的短行、代码块前的中文短标题 → 加粗小标题
- 合并相邻代码块、收敛多余空行
关键设计:幂等 (跑多少遍结果一样)、文字零丢失,图片、表格、颜色全保留;全库整理前自动 zip 备份。
2.4 笔记 PDF 一键导入(本文技术含量最高的部分)
选中笔记软件导出的 PDF(带"分区xx 的第N页"页脚的那种),程序自动:
- 按页脚
分区xx 的第N页还原分区结构(实测 191 页 12 个分区零失配) - 按双栏排版自动分栏重排阅读顺序
- 文字 + 原位图片一起导入为可编辑内容(不是截图贴图)
- 页眉日期变成笔记时间,孤立的项目符号、标点自动清理
2.5 搜索 + 替换
Ctrl+F 呼出右侧搜索面板:即时全文检索(标题 + 正文),结果带分区色点;替换行支持本页、整库替换(保留格式的安全替换,标题一并处理);回车循环跳转。

2.6 其它
- 导出 PDF(当前页、分区、整库,每篇笔记新起一页带页眉,191 篇约 3 秒)
- 表格粘贴:Excel、Word 等办公软件里的表格直接 Ctrl+V 变成真表格
- 图片 :粘贴即存本地;四角手柄拖拽等比缩放;拖图片本体可挪到任意位置(含表格单元格内);双击打开查看器;显示层做了平滑重采样(告别缩放锯齿)
- 数据即文件夹 :
Notebook\下每页一个 HTML,图片独立存放------拷文件夹就是备份,浏览器能直接打开 - 窗口布局、分栏宽度记忆,小屏自适应,命令行批量导入(
WorkNotes.exe --import x.pdf)
三、技术架构
PySide6 6.7 + PyInstaller(onefile,63MB)
src/
├── main.py 入口 + CLI(--import / --tidy)
├── ui_main.py 主窗口/分区条/搜索面板/Toast 反馈
├── editor.py 富文本编辑器 + 图片手柄缩放/拖放
├── store.py 存储(notebook.json 索引 + HTML/图片文件)
├── pdf_import.py 笔记 PDF 解析导入
├── paste_html.py Office 剪贴板表格解析
├── replace_text.py 查找替换
├── tidy.py 一键整理引擎
├── export_pdf.py PDF 导出(QPrinter)
└── theme.py 设计 tokens + 双主题 QSS
选择 QTextDocument 富文本体系的理由:编辑、HTML 持久化、打印(PDF)一条龙,且 HTML 是开放格式------十年后你的笔记仍然可读。
四、踩坑实录(干货)
坑 1:PyMuPDF 和 Qt 的 DLL 冲突 → 0xC0000005 崩溃
import fitz 必须放在 QApplication 初始化之后 ,否则直接访问违例崩溃(MuPDF 与 Qt 各自带 freetype)。解法:pdf_import 只在导入线程里延迟 import。
坑 2:PyInstaller 打包 fitz,exe 从 63MB 膨胀到 110MB
静态分析把 pandas、matplotlib、lxml、numpy 全拖进来。--exclude-module 逐个排除后回到 63MB,导入功能实测无损。
坑 3:表格"隐形"------内容都在,网格线消失
自己拼的表格 HTML 缺 border-style:solid,Qt 重新解析时用 Outset 边框(取调色板浅色绘制)------浅色主题下网格线近乎白色 ,用户看到的是"表格被删了"。教训:自拼 HTML 表格必须带 border-style:solid(Qt toHtml 的同款输出)。
坑 4:编辑器里的图片为什么发糊
Qt 内建文本图片绘制用快速缩放 ,且 ImageObject 是保留类型、无法用 registerHandler 替换。解法:运行时平滑派生------按"显示宽度 × 屏幕 DPI"预生成重采样缓存图供 1:1 显示,保存时自动还原原始引用(数据零膨胀)。
坑 5:Qt 的 doc.find 默认不区分大小写
QTextDocument.find(QString) 默认大小写不敏感 (和直觉相反),要区分必须显式传 FindCaseSensitively;更坑的是 find(QRegularExpression) 在 6.7.2 实测无视大小写选项------替换功能最终走纯字符串路径。
坑 6:exe 里按钮"点了没反应"=事件处理器抛异常被静默吞掉
windowed exe 无控制台,事件回调里的 AttributeError 完全无声。定位手段:离屏合成鼠标事件(QMouseEvent 逐个喂)做回归测试。这类问题必须在 CI 层拦住。
坑 7:Office 剪贴板表格会被 Qt 拍平
Excel 等办公软件复制出的 CF_HTML 带 o:、v: 命名空间标签,Qt 内建 HTML importer 解析不了表格结构。解法:检测到剪贴板 HTML 含 <table 时走自研解析器 (html.parser + 格式四栈),逐格重建 QTextTable。同理,部分软件复制图片时剪贴板里只有 HTML 引用(file:/// 或 data: URI)而无位图,也要单独处理。
五、获取与使用
- 完整版 :
WorkNotes.exe + Notebook\(我的示例笔记)一起拷走 - 空白版:单 exe + 说明,首次启动自动生成欢迎页,从零开始
- 运行要求:Win10/11 x64,免安装、无依赖、不写注册表
- 数据即文件夹:整个目录拷 U 盘 = 携带;拷一份 = 备份
六、写在最后
这个项目从"想要一个不联网的笔记"开始,最终变成 200+ 项自动化测试、双主题、可发布的完整工具。所有技术选型都遵循一条原则:数据主权归用户------HTML 明文存储、目录即数据库、任何时候可以带着数据离开。