《Python高级编程》6.1 事件循环的实现与调度
用 selectors 手写一个最小事件循环,再对照 CPython 的 BaseEventLoop._run_once,讲清就绪队列与定时器队列的双队列设计、call_soon 与 call_later 的调度优先级,以及本轮新注册回调为何延后,并附实测执行顺序。
tag
用 selectors 手写一个最小事件循环,再对照 CPython 的 BaseEventLoop._run_once,讲清就绪队列与定时器队列的双队列设计、call_soon 与 call_later 的调度优先级,以及本轮新注册回调为何延后,并附实测执行顺序。
给命令行工具加一层窗口:讲清 Tkinter 的 Tk/Frame/布局管理器与事件循环、PySide6 的信号槽与 MVC 思路,以及 GUI 与业务逻辑解耦的关键原则,并用假视图把控制器逻辑真跑通测试(本机无 GUI 环境,窗口代码为伪代码)。
把 14.1 的工具真正交到用户手里:讲清 console_scripts 入口点、用标准库 zipapp 真打包真运行单文件可执行、踩过相对导入与包根的经典陷阱、把依赖 vendor 进归档,并说明 PyInstaller 的取舍(本机未装,仅配置与流程)。
把脚本能力包成真正的命令行工具:用 Click 8.5.0 的装饰器、命令组与共享上下文声明参数与子命令,再用 Typer 0.27.3 的类型标注重写同一个工具,真跑帮助、统计、词频与退出码,并用 CliRunner 把 CLI 层测透,完成工程化的分层与测试。
用本机实测数字拆解多进程的三笔开销:fork/spawn/forkserver 的进程启动成本、跨进程 pickle 序列化税、Queue 与 Pipe 的通道差异;再用 shared_memory 实测 numpy 数组的零拷贝共享,最后给出线程池与进程池的选型决策表。
先如实交代本机并非自由线程构建,再从 PEP 703 的对象头改造、偏向引用计数、延迟引用计数与 Python 临界区入手,讲清 CPython 如何在拿掉 GIL 后维持内存安全,并给出 C 扩展 Py_mod_gil 迁移与生态评估的完整框架。
从 CPython 源码机制出发拆解 GIL:解释器循环为何必须持有全局锁、切换间隔怎样在安全点强制释放线程,并用本机 10 核实测数据画出 CPU 密集与 I/O 密集的影响边界,顺带用实测纠正「counter += 1 会丢更新」这一流传很广的误解。
脚本要有人在对的时间触发:本节讲透 cron 表达式与 crontab 写法、systemd timer 单元文件(Linux 配置,本机 macOS 未实测)、launchd plist,并用 fcntl 文件锁真跑防重入、用 state 文件做幂等、日志落盘。
把手工填表交给脚本:本节用 openpyxl 3.1.5 读写 Excel(样式、公式、只读模式),python-docx 1.2.0 生成 Word 与模板占位符替换,pypdf 6.19.0 合并拆分与提取文本,全部真跑并贴真实输出,附公式不自动计算的坑。
文件批处理最怕「一跑就毁数据」:本节用 pathlib / shutil / hashlib 真跑批量重命名、按规则归类、内容哈希去重与空目录清理,并讲透「先干跑再执行」的工程纪律、原子重命名与跨盘移动,以及 os.walk 对比 Path.walk 的取舍。
MCP 多语言 SDK 生态全景:Python/Go/Rust 官方与社区 SDK 的对比选型、类型系统与异步模型、自定义 SDK 的传输层与协议层实现、框架绑定(LangChain/LlamaIndex),帮你选对语言落地 MCP。
把 Python、Node、Rust 项目打进 Nix 的难点不在编译,而在依赖锁定与原生库链接。本文详解 poetry2nix 与 uv2nix、node2nix 与 pnpm、naersk 与 crane 的打包机制、固定输出派生的哈希坑、devShell 与构建分离,以及选型建议。
本节用标准库 tracemalloc 做快照对比,把一次真实泄漏定位到具体行:两次各 500 个事件后,泄漏行的分配增量是 +527.9 KiB、+500 次分配;再用 objgraph 的 show_growth 与 find_backref_chain 画出 module→globals→_REGISTRY→Session 的引用链,并说明本机无 graphviz 时只能用文本 API。
本节用 sys.getsizeof 逐类实测 int/str/list/dict/tuple 与自定义实例的字节数,讲清 PyObject 头 16 字节、PyVarObject 与容器指针数组的布局,并给出一个反直觉结论:__slots__ 实例本体反而比 __dict__ 实例更大,省下的是整块 __dict__;再用 100 万实例实测 92.0MB 对 53.8MB 的真实差距。
本节拆开 CPython 的引用计数与循环 GC:用 sys.getrefcount 实测引用数随赋值、入容器、传参的增减,看清循环引用为何让 refcount 归零失败;再用 gc 模块实测三代阈值 (2000,10,10)、各代 collect 的回收数、__del__ 与 gc.garbage 的边界,并给出关闭 GC 后循环垃圾堆积的真实 RSS 数字。
把采集从「能跑」做到「能长期跑」:用 urllib.robotparser 实测解析 robots.txt,真跑令牌桶限速器与指数退避重试,用 JSONL 做断点续采,最后收束成一页合规边界清单——只抓公开数据、尊重 robots 与 ToS、控制频率、不绕过反爬。
先跑通一个 JS 渲染的本地动态页,看清「静态解析抓不到」的真相,再用内嵌 JSON 与底层 API 两条替代路线实测拿到数据;浏览器自动化(Playwright / Selenium)本机未安装,只给伪代码、选型对比与等待策略,并划清与反爬的边界。
从 requests 2.34.2 与 httpx 0.28.1 的取舍讲起,实测连接复用、超时分层与重试策略,再用 http.server 起本地假站点,跑通 BeautifulSoup 4.15.0 + lxml 6.1.3 的 CSS 选择器与 XPath,并处理中文乱码与 httpx 系统代理两个真坑。
先实测本机 3.14.6 是否启用 JIT(sys._jit.is_available() 为 False),再拆开 CPython 的三层执行体系:自适应专门化字节码、Tier 2 微操作 IR 与 copy-and-patch 机器码,并梳理 3.13 引入、3.14 进入官方二进制的 JIT 演进与 tail-call 解释器。
实测运行时代码改写的三条路径:直接改 co_code / co_consts 与 CodeType.replace、用 bytecode 0.19.1 在指令层注入调用计数器,以及 3.12+ 的 sys.monitoring。含栈平衡校验边界与三条路径的开销对照(settrace 5.7 倍 vs monitoring 1.7 倍)。