Watchdog库是Python中一个用于监控文件系统变化的第三方库。它能够实时监测文件或目录的创建、修改、删除等操作,并在这些事件发生时触发相应的处理逻辑,因此也被称为文件看门狗。

Watchdog库的官方仓库见:watchdog,Watchdog库的官方文档见:watchdog-doc。Watchdog库的安装命令如下:

python -m pip install -U watchdog

注意:Watchdog库最新版本(2.1.5以上版本)需在Python3.9以上版本运行。若使用Python3.4或3.5,应选用Watchdog版本低于1.0.0;若使用Python3.6至3.8,应选用Watchdog版本低于2.0.0。

1 使用示例

基础示例

以下示例程序将以递归方式监控指定目录及其子文件夹中文件系统的变化情况,包括文件或文件夹的创建、修改、移动、删除,并将这些变化记录到控制台中:

import sys
# 导入logging模块,用于记录程序运行时的日志信息
import logging
# 从watchdog.observers模块中导入Observer类,用于监控文件系统的变化
from watchdog.observers import Observer
# 从watchdog.events模块中导入LoggingEventHandler类,用于处理文件系统事件并记录日志
from watchdog.events import LoggingEventHandler if __name__ == "__main__":
# 配置日志记录的基本设置
# level=logging.INFO表示只记录INFO级别及以上的日志信息
# format='%(asctime)s - %(message)s'指定日志的输出格式,包含时间戳和日志消息
# datefmt='%Y-%m-%d %H:%M:%S'指定时间戳的格式
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
# 指定要监控的文件夹路径,该文件夹必须存在
path = "demo_folder"
# 创建一个LoggingEventHandler对象,用于处理文件系统事件并记录日志
event_handler = LoggingEventHandler()
# 创建一个Observer对象,用于监控文件系统的变化
observer = Observer()
# 安排观察者监控指定路径下的文件系统事件
# event_handler是事件处理程序
# path是要监控的路径
# recursive=True表示递归监控该路径下的所有子文件夹
observer.schedule(event_handler, path, recursive=True)
# 启动观察者,开始监控文件系统的变化
observer.start()
try:
# 当观察者处于活动状态时,持续循环
while observer.is_alive():
# 等待1秒,让观察者有时间处理文件系统事件
observer.join(1)
finally:
# 停止观察者,结束文件系统的监控
observer.stop()
# 等待观察者线程结束
observer.join()

Watchdog事件类介绍

Watchdog库提供了一系列事件类,用于监控文件系统的各种变化,这些变化包括:

  • 创建事件on_create:涵盖文件和文件夹的创建情况,当有新的文件或者文件夹在监控路径下生成时触发相应事件。
  • 删除事件on_delete:当文件或者文件夹被从监控路径中移除时触发,分别有针对文件和文件夹的不同事件类。
  • 修改事件on_modified:文件夹内新增、删除文件或子文件夹等内容变化时触发文件夹修改事件。
  • 移动 / 重命名事件on_moved:文件或文件夹的位置发生移动,或者名称被更改时触发相应事件,该事件会记录原路径和新路径。

基于这些变化Watchdog库中存在8个事件类:

事件类名 触发场景
FileCreatedEvent 新文件被创建时触发
DirCreatedEvent 新文件夹被创建时触发
FileDeletedEvent 文件被删除时触发
DirDeletedEvent 文件夹被删除时触发
FileModifiedEvent 文件内容被修改时触发
DirModifiedEvent 文件夹内容(如添加、删除子文件或子文件夹)发生变化时触发
FileMovedEvent 文件被移动或重命名时触发
DirMovedEvent 文件夹被移动或重命名时触发

注意:在某些情形下,多个Watchdog事件可能会一同触发,这往往和文件系统操作的特性以及Watchdog对这些操作的响应机制有关。例如,当移动一个文件时,会同时触发FileMovedEvent(文件移动事件)和FileDeletedEvent(文件删除事件),因为移动文件的操作在源路径上相当于删除文件,同时在目标路径上会触发FileCreatedEvent(文件创建事件)。

以下代码的主要功能是监控指定目录下文件系统的各种事件,如文件或目录的创建、删除、移动和修改,并对这些事件进行重写和相应的处理:

# 该类用于处理文件系统事件,如文件的创建、删除、修改等
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer # 定义一个自定义的文件事件处理类,继承自FileSystemEventHandler
class FileEventHandler(FileSystemEventHandler):
def __init__(self):
FileSystemEventHandler.__init__(self)
# 初始化一个空列表,用于存储文件名
self.file_names = [] # 当文件或目录被移动时触发此方法
def on_moved(self, event):
# 判断是否是目录移动
if event.is_directory:
# 打印目录移动的信息
print(f"目录从 {event.src_path} 移动到 {event.dest_path}")
else:
# 打印文件移动的信息
print(f"文件从 {event.src_path} 移动到 {event.dest_path}") # 当文件或目录被创建时触发此方法
def on_created(self, event):
# 判断是否是目录创建
if event.is_directory:
# 打印目录创建的信息
print(f"目录已创建: {event.src_path}")
else:
# 打印文件创建的信息
print(f"文件已创建: {event.src_path}")
# 从文件的完整路径中提取文件名
file_full_name = str(event.src_path.split('/')[-1])
if file_full_name.endswith('.csv'):
# 如果是csv文件,将其添加到文件名列表中
self.file_names.append(file_full_name)
# 打印文件名列表
print(self.file_names) # 当文件或目录被删除时触发此方法
def on_deleted(self, event):
# 判断是否是目录删除
if event.is_directory:
# 打印目录删除的信息
print(f"目录已删除: {event.src_path}")
else:
# 打印文件删除的信息
print(f"文件已删除: {event.src_path}") # 当文件或目录被修改时触发此方法,注释代码表示不触发修改事件
# def on_modified(self, event):
# pass if __name__ == "__main__":
# 创建一个Observer对象,用于监控文件系统的变化
observer = Observer()
# 创建一个自定义的文件事件处理对象
event_handler = FileEventHandler()
# 定义要监控的目录
watch_directory = "demo_folder"
# 将事件处理对象和要监控的目录添加到观察者中,并设置为递归监控
observer.schedule(event_handler, watch_directory, recursive=True)
# 启动观察者,开始监控文件系统的变化
observer.start()
try:
# 当观察者处于活动状态时,持续循环
while observer.is_alive():
# 等待1秒,让观察者有时间处理文件系统事件
observer.join(1)
finally:
# 停止观察者,结束文件系统的监控
observer.stop()
# 等待观察者线程结束
observer.join()

快照功能

采用基于定时器的批处理策略,合并并延迟频繁的文件变更事件,能够有效降低系统负载。具体做法是:当系统检测到文件首次变动时,启动可重置的计时器,在设定的延迟期内累积后续变更事件,待计时器超时后,再统一通过对比当前文件系统状态与上次缓存快照,可精准识别所有变更项。具体实现代码如下:

import time
import os
import threading
from watchdog.observers import Observer
from watchdog.events import *
from watchdog.utils.dirsnapshot import DirectorySnapshot, DirectorySnapshotDiff class FileChangeHandler(FileSystemEventHandler):
def __init__(self, monitored_path, delay=0.5):
# 调用父类构造函数
super().__init__()
# 被监控的目录路径
self.monitored_path = monitored_path
self.delay = delay
# 定时器对象,用于延迟检查
self.delay_timer = None
# 快照用于记录指定目录在某个时间点的状态,包含了目录下所有文件和子目录的信息,
# 记录目录的初始快照
self.initial_snapshot = DirectorySnapshot(self.monitored_path) def on_any_event(self, event):
# 通过定时器减少不必要的检查
# 如果定时器已存在,取消它
if self.delay_timer:
self.delay_timer.cancel()
# 创建一个新的定时器,延迟后执行检查快照的操作
# 通过快照检测文件系统变化
self.delay_timer = threading.Timer(self.delay, self._check_directory_changes)
self.delay_timer.start() def _check_directory_changes(self):
# 获取当前目录的新快照
new_snapshot = DirectorySnapshot(self.monitored_path)
# 计算新旧快照之间的差异
snapshot_difference = DirectorySnapshotDiff(self.initial_snapshot, new_snapshot)
# 更新初始快照为新快照
self.initial_snapshot = new_snapshot
# 清空定时器
self.delay_timer = None
# 打印目录变化信息
self._print_changes(snapshot_difference) def _print_changes(self, diff):
# 打印文件和目录的创建、删除、修改和移动信息
print("创建的文件:", diff.files_created)
print("删除的文件:", diff.files_deleted)
print("修改的文件:", diff.files_modified)
print("移动的文件:", diff.files_moved)
print("修改的目录:", diff.dirs_modified)
print("移动的目录:", diff.dirs_moved)
print("删除的目录:", diff.dirs_deleted)
print("创建的目录:", diff.dirs_created) class DirectoryMonitor:
def __init__(self, monitored_path):
# 被监控的目录路径
self.monitored_path = monitored_path
# 创建一个观察者对象
self.directory_observer = Observer() def start_monitoring(self):
# 创建文件变化处理对象
change_handler = FileChangeHandler(self.monitored_path)
# 安排观察者监控指定目录,递归地监控子目录
self.directory_observer.schedule(change_handler, self.monitored_path, recursive=True)
# 启动观察者
self.directory_observer.start() def stop_monitoring(self):
# 停止观察者
self.directory_observer.stop()
# 等待观察者线程结束
self.directory_observer.join() if __name__ == "__main__":
monitor = DirectoryMonitor("demo_folder")
# 开始监控
monitor.start_monitoring()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
monitor.stop_monitoring()

多文件夹监控

以下代码展示了通过schedule方法为每个目录注册事件处理程序,实现对多个目录的同步监控:

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class CustomFileEventHandler(FileSystemEventHandler):
def on_created(self, event):
    patterns = [“*.jpg”, “*.png”, “*.gif”] # 只监控图片文件    def on_modified(self, event):        print(f“图片文件有变化:{event.src_path}”)
entity = "directory" if event.is_directory else "file"
print(f"{entity} on_created: {event.src_path}") if __name__ == "__main__":
file_observer = Observer()
monitored_directories = ['demo_folder', 'demo_folder2']
file_event_handler = CustomFileEventHandler()
for directory in monitored_directories:
# 为每个目录注册事件处理程序
file_observer.schedule(file_event_handler, directory, recursive=True)
file_observer.start()
try:
# 当观察者处于活动状态时,持续循环
while file_observer.is_alive():
# 等待1秒,让观察者有时间处理文件系统事件
file_observer.join(1)
finally:
# 停止观察者,结束文件系统的监控
file_observer.stop()
# 等待观察者线程结束
file_observer.join()

2 参考

[python] 基于WatchDog库实现文件系统监控的更多相关文章

  1. [python] 基于diagrams库绘制系统架构图

    Python的Diagrams库允许通过简单的Python代码绘制云系统架构,实现对新的系统架构进行原型设计.Diagrams的官方仓库地址见:diagrams.Diagrams的官方文档和使用示例见 ...

  2. [python] 基于wordcloud库绘制词云图

    词云Wordcloud是文本数据的一种可视化表示方式.它通过设置不同的字体大小或颜色来表现每个术语的重要性.词云在社交媒体中被广泛使用,因为它能够让读者快速感知最突出的术语.然而,词云的输出结果没有统 ...

  3. [python] 基于blind-watermark库添加图片盲水印

    blind-watermark是一个能够给图片添加/解析基于频域的数字盲水印的Python库.图像水印image watermark是指在图片里添加文本或图形,以标记图片的来源.但是图像水印会破坏原图 ...

  4. [python] 基于paramiko库操作远程服务器

    SSH(Secure Shell)是一种网络安全协议,能够使两台计算机安全地通信和共享数据.目前,SSH协议已在世界各地广泛使用,大多数设备都支持SSH功能.SSH的进一步说明见:深入了解SSH.SS ...

  5. python基于pillow库的简单图像处理

    from PIL import Image from PIL import ImageFilter from PIL import ImageEnhance import matplotlib.pyp ...

  6. Python 基于request库的get,post,delete,封装

    # coding=utf-8 import json import requests class TestApi(object): """ /* @param: @ses ...

  7. 基于python爬虫的github-exploitdb漏洞库监控与下载

    基于python爬虫的github-exploitdb漏洞库监控与下载 offensive.py(爬取项目历史更新内容) #!/usr/bin/env python # -*- coding:utf- ...

  8. python 各种开源库

    测试开发 来源:https://www.jianshu.com/p/ea6f7fb69501 Web UI测试自动化 splinter - web UI测试工具,基于selnium封装. 链接 sel ...

  9. Python常用的库简单介绍一下

    Python常用的库简单介绍一下fuzzywuzzy ,字符串模糊匹配. esmre ,正则表达式的加速器. colorama 主要用来给文本添加各种颜色,并且非常简单易用. Prettytable ...

  10. Python的常用库

    读者您好.今天我将介绍20个属于我常用工具的Python库,我相信你看完之后也会觉得离不开它们.他们是: Requests.Kenneth Reitz写的最富盛名的http库.每个Python程序员都 ...

随机推荐

  1. 鸿蒙页面开发 - 组件复用样式 @Styles

    这篇文章介绍一个装饰器 @Styles 他的主要作用是: 当多个组件都有相同的样式,如果每个组件单独设置,会造成大量重复的代码冗余.这时我们可以使用 @Styles 将这些相同样式封装成一个方法,供这 ...

  2. AAAT 笔记(P5649)

    实际上去掉主函数不长于线段树 3. 对于 LCT 每个点的虚儿子.用 splay 把它们串起来(称为新 splay,虽然是共用的). 具体来说,设 \(1\le x\le n\) 是原 LCT 的 s ...

  3. Luogu P10842 Piggy and Trees 题解 [ 绿 ] [ 拆边 ] [ 贡献思维 ] [ 组合数学 ]

    Piggy and Trees:把路径拆成边的思维题. 思路 一看到这题的路径,就想到了 Luogu P3177 树上染色 这题化路径为边的贡献,分别计算的思维. 那么对于此题,先来观察题目里式子的意 ...

  4. CSP-J/S2023游记

    过了将近一年才回来补游记 Day -22 光速报名 Day -21~0 国庆假期+痛苦的whk Day 1 CSP-J 早上乘出租车风驰电掣赶到连大,在门口等半天发现已经可以进去了. 一路踩着爆浆的银 ...

  5. flutter-路由传值携带中文时,报错

    解决方案: 路由采用了第三方:fluro 1 Application.router.navigateTo(context, "/searchresult?word=${Uri.encodeC ...

  6. C语言程序设计手写笔记

    最近自己录了一个自学C语言系列,笔记发出来,视频还在传

  7. 洛谷B3843 [GESP202306 三级] 密码合规 题解

    原题传送门 前言 咳咳,由于本人最近在备考GESP三级,所以可能会有很多水的题解.(见谅--见谅--) 由于今天刚刚重新刷了一遍此题,所以记忆犹新.(太菜了!一个测试点都能 WA ) 题目解析 简单的 ...

  8. ITSM运维管理整理总结

    ITSM 和我们平常所说的软件管理最大的不同? 目标不是管理技术,主要任务是管理用户和客户的IT需求 2.人员.技术.流程[重要] 3.几大模块 模块名称 干什么 备注 服务台 1.对接客户的前方,负 ...

  9. cypress 在 typescript 项目中报错找不到 'tslib'

    原文链接:https://blog.jijian.link/2020-08-11/cypress-typescript-cannot-find-module-tslib/ cypress 在 type ...

  10. [Qt 基础内容-05] QDialogButtonBox

    QDialogButtonBox 本文主要根据QT官方帮助文档以及日常使用,简单的介绍一下QDialogButtonBox的功能以及使用 文章目录 QDialogButtonBox 简介 信号和槽 基 ...