macOS Big Sur下Python watchdog监控文件修改无响应问题排查
故障原因
- macOS 系统下 watchdog 默认使用的 FSEvents 事件框架对单文件监控的支持存在缺陷,FSEvents 本身是面向目录级事件设计的,直接传入单个文件路径时经常无法捕获到修改事件。
- 你当前监控的是 SMB 网络挂载路径的文件,macOS 对网络挂载卷的文件系统事件上报逻辑和本地磁盘存在差异,进一步放大了单文件监控的失效问题。
- 部分编辑器/程序修改文件时采用原子写入策略(先生成临时文件再替换原文件),此时触发的不是
on_modified事件,而是on_moved/on_created事件,也会导致回调不触发。
修复方案
调整为监控目标文件所在的目录,在事件回调中过滤匹配目标文件名,同时覆盖多种文件变更事件确保触发,修改后代码如下:
#!/usr/bin/python3 import time import os from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler # 目标文件绝对路径 TARGET_FILE = '/Users/jeff/smb/storage/wsjt-x/wsjtx_log.adi' # 提取目标文件所在目录和文件名 WATCH_DIR = os.path.dirname(TARGET_FILE) TARGET_FILENAME = os.path.basename(TARGET_FILE) class MyHandler(FileSystemEventHandler): def on_any_event(self, event): # 过滤目录事件,只处理文件事件 if event.is_directory: return # 匹配目标文件名 if os.path.basename(event.src_path) == TARGET_FILENAME: print('file changed') if __name__ == "__main__": event_handler = MyHandler() observer = Observer() # 改为监控目录,recursive根据需求调整 observer.schedule(event_handler, path=WATCH_DIR, recursive=False) observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: observer.stop() observer.join()
如果调整为目录监控后仍有异常,可以强制 watchdog 在 macOS 下使用兼容性更好的 kqueue 事件模型,替换导入的观察者类即可:
# 把原本的Observer导入替换为下面的代码 from watchdog.observers.kqueue import KqueueObserver as Observer
内容的提问来源于stack exchange,提问作者Alan
相关产品推荐
相关产品推荐

