python watchdog占用_watchdog 监控文件变化使用总结

概述

首先声明,本文讨论的 watchdog,不是单片机里的 watchdog,也不是 linux 中的 watchdog,而是 python 世界里用来监视文件系统变化的一个第三方模块。在 python 中文件监视主要有两个库,一个是 pyinotify,一个是 watchdog。pyinotify 依赖于 linux 平台的 inotify 机制,只能应用在 linux 平台上。watchdog 则对不同平台的的事件都进行了封装,不仅可以监视 windows 文件系统,也可以监视 linux 的文件系统。

文件系统事件类

文件系统事件基类定义如下:

watchdog.events.FileSystemEvent(event_type, src_path, is_directory=False)

# event.event_type - 事件类型,为 moved / deleted / created / modified 其中之一

# event.src_path - 触发该事件的文件或目录路径

# event.is_directory - 该事件是否由一个目录触发

由 watchdog.events.FileSystemEvent 基类派生的子类如下:

watchdog.events.FileDeletedEvent()

# 文件被删除时触发该事件

watchdog.events.DirDeletedEvent()

# 目录被删除时触发该事件

watchdog.events.FileCreatedEvent()

# 文件被创建时触发该事件

watchdog.events.DirCreatedEvent()

# 目录被创建时触发该事件

watchdog.events.FileModifiedEvent()

# 文件被修改时触发该事件(修改文件内容、修改文件inode信息如权限和访问时间,都会触发该事件)

watchdog.events.DirModifiedEvent()

# 目录被修改时触发该事件

watchdog.events.FileMovedEvent()

# 文件被移动或重命名时触发该事件,因为涉及文件移动,所以除了event.src_path表示原路径,还有event.dest_path表示目的路径

watchdog.events.DirMovedEvent()

# 目录被移动或重命名时触发该事件,因为涉及文件移动,所以除了event.src_path表示原路径,还有event.dest_path表示目的路径

文件系统事件处理类

watchdog.events.FileSystemEventHandler 是事件处理器的基类,用于处理事件,用户需继承该类,并在子类中重写对应方法。需要用户重写的方法有:

self.on_any_event(event)

# 任何事件发生都会首先执行该方法,该方法默认为空,dispatch()方法会先执行该方法,然后再把 event 分派给其他方法处理

self.on_moved(event)

# 处理 DirMovedEvent 和 FileMovedEvent 事件,默认为空

self.on_created(event)

# 处理 DirCreatedEvent 和 FileCreatedEvent 事件,默认为空

self.on_deleted(event)

# 处理 DirDeletedEvent 和 FileDeletedEvent 事件,默认为空

self.on_modified(event)

# 处理 DirModifiedEvent 和 FileModifiedEvent 事件,默认为空

以上方法中,event 有几个属性可用:

event.is_directory - 触发事件的是否为文件夹

event.src_path - 源路径

event.dest_path - 目标路径

最简单的应用示例

下面的例子展示了如何监视 D:\XufiveGit\PEC\client 文件夹内所有文件的 moved / deleted / created / modified。请注意,重命名被视为 moved (移动)。

#-*- coding: utf-8 -*-

from watchdog.observers importObserverfrom watchdog.events import *

classFileEventHandler(FileSystemEventHandler):defon_any_event(self, event):pass

defon_moved(self, event):ifevent.is_directory:print("directory moved from {0} to {1}".format(event.src_path,event.dest_path))else:print("file moved from {0} to {1}".format(event.src_path,event.dest_path))defon_created(self, event):ifevent.is_directory:print("directory created:{0}".format(event.src_path))else:print("file created:{0}".format(event.src_path))defon_deleted(self, event):ifevent.is_directory:print("directory deleted:{0}".format(event.src_path))else:print("file deleted:{0}".format(event.src_path))defon_modified(self, event):ifevent.is_directory:print("directory modified:{0}".format(event.src_path))else:print("file modified:{0}".format(event.src_path))if __name__ == "__main__":importtime

observer=Observer()

event_handler=FileEventHandler()

observer.schedule(event_handler, r"D:\XufiveGit\PEC\client", True) # 执行模块,是否递归监控

observer.start()try:whileTrue:

time.sleep(1)exceptKeyboardInterrupt:

observer.stop()

存在的问题

真正测试过之后,你会发现,上面的例子几乎没有实用价值,因为,文件操作引发的事件比我们想象的多了不少,而且难以在事件函数中做出针对性处理。

比如,添加一个文件,势必引发 created 事件,同时也会导致所在文件夹的 modified 事件,如果该文件目录比较深,还会引发多层父级文件夹的 modified 事件。

如果,你觉得这不算什么问题,那么,在 windows 平台上每一次的文件修改引发两次 modified 事件,算不算一个令人头疼的问题呢?

在 linux 平台上表现如何,我没有测试过,但在 windows 平台上,由于 watchdog 封装的是 windows 系统的 FileSystemWatcher Events,

处理文件的过程中执行了多次文件系统操作,无法避免地触发了多次事件。

改进方案

如果对监视文件的实时性要求不高,又懒得处理一大堆事件,那么,比较事件前后的文件夹快照就是一个值得尝试的改进方案。实现这个思路,有三个前提条件:

快速获取文件夹快照。幸运的是,watchdog 模块为我们提供了 DirectorySnapshot 功能

可以接受200毫秒的延时。文件操作引发的一大堆事件会集中在一个较短的时间内,一般情况下,在文件操作之后200毫秒获取文件夹快照,是一个不错的间隔

快速比较文件夹快照。这也不是问题,watchdog 模块有 DirectorySnapshotDiff 子模块

改进思路是这样的:设置一个定时器, 200毫秒后抓取快照,并与上一张快照比较。每当有事件发生时,检查定时器是否已经启动。如果未启动,则直接启动定时器;否则,说明该事件距离上次事件不足200毫秒,可视为是同一组事件,此时终止定时器,再次重启。具体代码如下:

#-*- coding: utf-8 -*-

importos, threadingfrom watchdog.observers importObserverfrom watchdog.events import *

from watchdog.utils.dirsnapshot importDirectorySnapshot, DirectorySnapshotDiffclassFileEventHandler(FileSystemEventHandler):def __init__(self, aim_path):

FileSystemEventHandler.__init__(self)

self.aim_path=aim_path

self.timer=None

self.snapshot=DirectorySnapshot(self.core.proj_path)defon_any_event(self, event):ifself.timer:

self.timer.cancel()

self.timer= threading.Timer(0.2, self.checkSnapshot)

self.timer.start()defcheckSnapshot(self):

snapshot=DirectorySnapshot(self.aim_path)

diff=DirectorySnapshotDiff(self.snapshot, snapshot)

self.snapshot=snapshot

self.timer=None#下面是应处理的各种事项

print("files_created:", diff.files_created)print("files_deleted:", diff.files_deleted)print("files_modified:", diff.files_modified)print("files_moved:", diff.files_moved)print("dirs_modified:", diff.dirs_modified)print("dirs_moved:", diff.dirs_moved)print("dirs_deleted:", diff.dirs_deleted)print("dirs_created:", diff.dirs_created)#接下来就是你想干的啥就干点啥,或者该干点啥就干点啥

pass

classDirMonitor(object):"""文件夹监视类"""

def __init__(self, aim_path):"""构造函数"""self.aim_path=aim_path

self.observer=Observer()defstart(self):"""启动"""event_handler=FileEventHandler(self.aim_path)

self.observer.schedule(event_handler, self.aim_path, True)

self.observer.start()defstop(self):"""停止"""self.observer.stop()if __name__ == "__main__":

monitor= DirMonitor(r"D:\XufiveGit\PEC\client")

monitor.start()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这里是Python使用watchdog库对文件进行监控的代码示例: ``` import time from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler class MyHandler(FileSystemEventHandler): def on_any_event(self, event): # 监控到任何事件都会触发该函数 if event.is_directory: return elif event.event_type == 'created': # 处理文件创建事件 print("文件创建:", event.src_path) elif event.event_type == 'modified': # 处理文件修改事件 print("文件修改:", event.src_path) elif event.event_type == 'deleted': # 处理文件删除事件 print("文件删除:", event.src_path) if __name__ == "__main__": event_handler = MyHandler() observer = Observer() observer.schedule(event_handler, path='/path/to/watch', recursive=True) observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: observer.stop() observer.join() ``` 在代码中,FileSystemEventHandler 是watchdog库提供的一个类,用于处理文件系统事件。在这个类中,我们可以重写 on_any_event() 方法,该方法会在监控目录中有任何文件事件发生时触发。通过判断事件类型,我们可以处理不同的事件。 在主程序中,我们创建了一个 MyHandler 的实例 event_handler,并将其与监控路径绑定。然后创建了一个 Observer 的实例 observer,并将其与 event_handler 绑定。接着,我们启动了 observer,不断监控指定路径的文件变化。当用户按下 Ctrl+C 时,我们会通过 observer.stop() 停止监控,并通过 observer.join() 等待 observer 线程结束。 请注意,在使用该代码前,你需要先安装 watchdog 库,可以使用 pip install watchdog 命令进行安装。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值