watchdog监控文件变化使用总结——转载
原文链接地址:https://blog.csdn.net/xufive/article/details/93847372
概述
首先声明,本文讨论的 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 import Observer
from watchdog.events import *
class FileEventHandler(FileSystemEventHandler):
def on_any_event(self, event):
pass
def on_moved(self, event):
if event.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))
def on_created(self, event):
if event.is_directory:
print("directory created:{0}".format(event.src_path))
else:
print("file created:{0}".format(event.src_path))
def on_deleted(self, event):
if event.is_directory:
print("directory deleted:{0}".format(event.src_path))
else:
print("file deleted:{0}".format(event.src_path))
def on_modified(self, event):
if event.is_directory:
print("directory modified:{0}".format(event.src_path))
else:
print("file modified:{0}".format(event.src_path))
if __name__ == "__main__":
import time
observer = Observer()
event_handler = FileEventHandler()
observer.schedule(event_handler, r"D:\XufiveGit\PEC\client", True)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
存在的问题
真正测试过之后,你会发现,上面的例子几乎没有实用价值,因为,文件操作引发的事件比我们想象的多了不少,而且难以在事件函数中做出针对性处理。比如,添加一个文件,势必引发 created 事件,同时也会导致所在文件夹的 modified 事件,如果该文件目录比较深,还会引发多层父级文件夹的 modified 事件。
如果,你觉得这不算什么问题,那么,在 windows 平台上每一次的文件修改引发两次 modified 事件,算不算一个令人头疼的问题呢?在 linux 平台上表现如何,我没有测试过,但在 windows 平台上,由于 watchdog 封装的是 windows 系统的 FileSystemWatcher Events,处理文件的过程中执行了多次文件系统操作,无法避免地触发了多次事件。
改进方案
如果对监视文件的实时性要求不高,又懒得处理一大堆事件,那么,比较事件前后的文件夹快照就是一个值得尝试的改进方案。实现这个思路,有三个前提条件:
快速获取文件夹快照。幸运的是,watchdog 模块为我们提供了 DirectorySnapshot 功能
可以接受200毫秒的延时。文件操作引发的一大堆事件会集中在一个较短的时间内,一般情况下,在文件操作之后200毫秒获取文件夹快照,是一个不错的间隔
快速比较文件夹快照。这也不是问题,watchdog 模块有 DirectorySnapshotDiff 子模块
改进思路是这样的:设置一个定时器, 200毫秒后抓取快照,并与上一张快照比较。每当有事件发生时,检查定时器是否已经启动。如果未启动,则直接启动定时器;否则,说明该事件距离上次事件不足200毫秒,可视为是同一组事件,此时终止定时器,再次重启。具体代码如下:
#-*- coding: utf-8 -*-
import os, threading
from watchdog.observers import Observer
from watchdog.events import *
from watchdog.utils.dirsnapshot import DirectorySnapshot, DirectorySnapshotDiff
class FileEventHandler(FileSystemEventHandler):
def __init__(self, aim_path):
FileSystemEventHandler.__init__(self)
self.aim_path = aim_path
self.timer = None
self.snapshot = DirectorySnapshot(self.core.proj_path)
def on_any_event(self, event):
if self.timer:
self.timer.cancel()
self.timer = threading.Timer(0.2, self.checkSnapshot)
self.timer.start()
def checkSnapshot(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
class DirMonitor(object):
"""文件夹监视类"""
def __init__(self, aim_path):
"""构造函数"""
self.aim_path= aim_path
self.observer = Observer()
def start(self):
"""启动"""
event_handler = FileEventHandler(self.aim_path)
self.observer.schedule(event_handler, self.aim_path, True)
self.observer.start()
def stop(self):
"""停止"""
self.observer.stop()
if __name__ == "__main__":
monitor = DirMonitor(r"D:\XufiveGit\PEC\client")
monitor.start()
完毕
watchdog监控文件变化使用总结——转载的更多相关文章
- Python监控文件变化:watchdog
Python监控文件变化有两种库:pyinotify和watchdog.pyinotify依赖于Linux平台的inotify,后者则对不同平台的的事件都进行了封装.也就是说,watchdog跨平台. ...
- JDK 之 NIO 2 WatchService、WatchKey(监控文件变化)
JDK 之 NIO 2 WatchService.WatchKey(监控文件变化) JDK 规范目录(https://www.cnblogs.com/binarylei/p/10200503.html ...
- mac 监控文件变化并重启php
自己撸一个框架,需要监控代码变化 安装fswatch brew install fswatch shell重启PHP脚本reload.sh #!/bin/sh do ps -ef | grep php ...
- inotifywait命令如何监控文件变化?
转载自:https://segmentfault.com/a/1190000038351925 文件监控可以配合rsync实现文件自动同步,例如监听某个目录,当文件变化时,使用rsync命令将变化的文 ...
- linux 监控文件变化
介绍 有时候我们常需要当文件变化的时候便触发某些脚本操作,比如说有文件更新了就同步文件到远程机器.在实现这个操作上,主要用到两个工具,一个是rsync,一个是inotifywait .inotifyw ...
- Gulp-前端进阶A-3---如何不刷新监控文件变化?
npm install --save-dev gulp-connect npm install --save-dev gulp-livereload npm其他,前面已有 var gulp = req ...
- 使用apache common-io 监控文件变化--转
package common.io; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.common ...
- 利用nodejs监控文件变化并使用sftp上传到服务器
很久没写博客了,因为最近在用react+express做一个自己的工具型网站(其实就是夺宝岛抢拍器) 然后因为经常要改动,而且又要放到服务器上进行测试.总是要webpack,然后手动把文件上传上去,不 ...
- 使用apache common-io 监控文件变化
package common.io; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.common ...
随机推荐
- Kerberos身份验证流程
介绍:Kerberos 是一种由 MIT(麻省理工大学)提出的一种网络身份验证协议.它旨在通过使用密钥加密技术为客户端/服务器应用程序提供强身份验证. 在 Kerberos 认证中,最主要的问题是如何 ...
- 含-SH的ACE抑制药的青霉胺样反应
关于 含-SH的血管紧张素转化酶(ACE)抑制药如卡托普利具有青霉胺样反应.而依那普利则不含-SH. 青霉胺样反应 青霉胺样反应,指应用含-SH的ACE抑制药产生的皮疹.嗜酸性粒细胞(E)增多.味觉异 ...
- How to change hostname on debian
How to change hostname on Debian 10 Linux last updated July 13, 2019 in CategoriesDebian / Ubuntu, L ...
- WinDbg常用命令系列---.cmdtree
.cmdtree 简介 使用形式 .cmdtree cmdfile 参数 cmdfile命令文件,包含多个你需要的命令.必须是一个文本档 使用步骤 1.使用命令创建文本文件test.wl,使用以下示例 ...
- web前端开发面试被虐篇(一)
地点:北京 职位:前端开发工程师 要求:达到中级开发,JS基础足够扎实,css基础扎实,要求纯手写代码 面试过程: 进门一个面相老成的大叔递给我一份题,说别的都不好使先做题看看水平,说话语气很温和明显 ...
- webapp接口安全设计思路
在做webqq或者说app开发的时候,免不了会有接口是有权限的(如查询用户敏感信息等),这时接口安全设计思路就非常重要了. 简单一点,在APP中保存登录数据,每次调用接口时传输 程序员总能给自己找到偷 ...
- [Beta]第三次 Scrum Meeting
[Beta]第三次 Scrum Meeting 写在前面 会议时间 会议时长 会议地点 2019/5/7 22:00 30min 大运村公寓6F寝室 附Github仓库:WEDO 例会照片 工作情况总 ...
- 第10组 Beta冲刺(4/5)
链接部分 队名:女生都队 组长博客: 博客链接 作业博客:博客链接 小组内容 恩泽(组长) 过去两天完成了哪些任务 描述 将数据分析以可视化形式展示出来 新增数据分析展示等功能API 服务器后端部署, ...
- 第09组 Beta冲刺(3/4)
队名:软工9组 组长博客:https://www.cnblogs.com/cmlei/ 作业博客:https://edu.cnblogs.com/campus/fzu/SoftwareEngineer ...
- Git提交(PUSH)时记住密码 - 不用每次都输入密码
开发使用的团队搭建好的GitLab服务器来作为项目共享开发,由于我不是最高权限,没办法把我git生成的SSH-Key放到服务器里面去,所有只好在每次提交的时候配置git config来记录密码不过期来 ...