watchdog是监控文件夹变动最可靠的Python方案,它封装Linux inotify、macOS FSEvents、Windows ReadDirectoryChangesW等原生API,避免轮询,实现低延迟、低开销的跨平台事件驱动监听。

用 watchdog 监控文件夹变动最可靠
Python 标准库没有跨平台的文件系统事件监听能力,watchdog 是目前最成熟、维护活跃的选择。它底层封装了各系统的原生 API(Linux 的 inotify、macOS 的 FSEvents、Windows 的 ReadDirectoryChangesW),避免轮询,低延迟且资源占用小。
安装只需:
pip install watchdog
关键点:不要用 time.sleep() + os.listdir() 轮询——效率低、漏事件、高 CPU;也不要自己调 ctypes 封装系统 API——跨平台适配成本极高。
FileSystemEventHandler 子类化是标准做法
所有事件响应逻辑都应通过继承 FileSystemEventHandler 并重写对应方法实现,而不是监听原始事件对象字段。这样语义清晰、可读性强,且自动过滤重复/中间状态(如编辑器保存时的临时文件)。
常用重写方法包括:
-
on_created(self, event):新建文件或目录 -
on_modified(self, event):文件内容或属性变更(注意:目录modified通常表示子项增删) -
on_moved(self, event):重命名或移动(event.src_path→event.dest_path) -
on_deleted(self, event):删除
示例片段:
from watchdog.events import FileSystemEventHandler<br>class MyHandler(FileSystemEventHandler):<br> def on_created(self, event):<br> if not event.is_directory:<br> print(f"新文件: {event.src_path}")
启动监听必须用 Observer + start(),别漏 join()
Observer 是后台线程管理器,必须显式调用 start() 才真正开始监听;若主线程退出而没阻塞,程序立即结束,监听无声终止。
常见错误写法:
observer = Observer()<br>observer.schedule(handler, path="/tmp", recursive=True)<br># 忘了 start() 或 join() —— 程序秒退,什么也不发生
正确结构:
observer = Observer()<br>observer.schedule(handler, path="/tmp", recursive=True)<br>observer.start()<br>try:<br> while True:<br> time.sleep(1) # 或用 signal.pause()<br>except KeyboardInterrupt:<br> observer.stop()<br>observer.join() # 必须调用,等待后台线程干净退出
注意:recursive=True 表示监听子目录,设为 False 只监控指定路径一级;observer.stop() 后必须跟 join(),否则可能残留线程。
过滤事件类型和路径要靠 PatternMatchingEventHandler 或手动判断
如果只关心特定后缀(如 .log)或排除某些路径(如 .swp 文件),直接在事件方法里用 os.path 判断最灵活。但更推荐用 PatternMatchingEventHandler,它内置通配符匹配,且自动跳过非匹配项,减少无谓回调。
示例:
from watchdog.events import PatternMatchingEventHandler<br>handler = PatternMatchingEventHandler(patterns=["*.py", "*.md"], ignore_patterns=["*/__pycache__/*"])<br>handler.on_created = lambda e: print("Python or Markdown added:", e.src_path)
注意:ignore_patterns 对路径生效(含目录名),patterns 对文件名生效;正则不支持,只能用 * 和 ?;大小写敏感性取决于操作系统。
真实场景中,编辑器(如 VS Code)保存时会先写临时文件再原子替换,可能触发多次 created + deleted,需结合 time.time() 去抖或检查文件大小是否稳定,这点容易被忽略。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











