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. DP(优化)

    史不分好坏.是史就应该冲进. 细节见其他题解. P10538 首先建出部分分 sub1 的图,发现是 DAG,于是设点为状态,即即将乘坐 \(j\) 车的最小代价 \(f_j\).这样的转移就是枚举上 ...

  2. 【H2O系列】包括人形机器人WBC相关论文小结

    1. 前言 这篇博客主要用于记录包括人形机器人WBC或locomotion相关论文小结. 一方面便于日后自己的温故学习,另一方面也便于大家的学习和交流. 如有不对之处,欢迎评论区指出错误,你我共同进步 ...

  3. 安川MH225机械手CPU单元维修解决方案

    在进行安川机器人cpu单元维修之前,我们需要做好充分的准备工作.首先,了解机器人的使用环境和历史情况,了解机器人出现故障的具体表现,例如:是否有异常震动.过热等现象.其次,准备必要的维修工具和备件,确 ...

  4. 软件工程: SDLC V模型

    V型 V-model 代表一个开发过程,可以被认为是瀑布模型的扩展,是更通用的 V-model 的一个例子.不是以线性方式向下移动,而是在编码阶段之后向上弯曲工艺步骤,以形成典型的 V 形.V 模型展 ...

  5. 火爆的 幻兽帕鲁/Palworld 单机➕联机 电脑游戏 免费畅游

    在广阔的世界中收集神奇的生物"帕鲁",派他们进行战斗.建造.做农活,工业生产等,这是一款支持多人游戏模式的全新开放世界生存制作游戏. ▼补丁主要内容 ・修复加载世界数据时,加载画面 ...

  6. Week09_day05(Hbase的介绍和工作原理)

    HBase是一个分布式的.面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文"Bigtable:一个结构化数据的分布式存储系统".就像Bigtable利 ...

  7. sql---索引总结

    索引:是为了提高数据查询的效率 常见模型: 哈希表(以键值对key-value存储数据的结构) 适应场景:哈希表这种结构适用于只有等值查询的场景 思路:把值放在数组里,用一个哈希函数把key换算成一个 ...

  8. 宝塔导入mysql数据库后,phpmyadmin可以登录,本地Navicat无法登录

    问题描述:宝塔导入mysql数据库后,phpmyadmin可以登录,本地Navicat无法登录 问题排查:1.检查服务器3306端口是否开启,如果为云服务器,需要登录云服务器后台安全组设置开启: 2. ...

  9. 报错:ReferenceError: __dirname is not defined in ES module scope

    报错: __dirname is not defined in ES module scope 前言 新版 NodeJS 支持通过 ESM 方式导入模块,代码如: // CommonJS 规范(旧) ...

  10. useSlots-TS

    import {useSlots, VNode} from 'vue'; export const useGetSlots = () => { const slots = useSlots(); ...