12. python watchdog系统看门狗

 


12. python watchdog系统看门狗

watchdog是一个用于监控文件系统事件的跨平台Python API库。

12.1 watchdog库的API

  • watchdog库采用观察者(监控器)模型,主要有3个角色,分别是观察者(Observer)、事件处理器(Event Handler)和被监控对象(事件)。这三个角色通过observer.schedule()调度函数关联起来,观察者不断检测,调用平台依赖代码对被监控对象进行更改监控,当发现文件系统更改时,通知事件处理器去处理。

(1)定义文件系统事件的类

  • 文件系统事件基类watchdog.events.FileSystemMovedEvent(FileSystemEvent)表示被监控对象发生更改时触发的文件系统事件。
    • 事件基类不用定义,可以在事件处理器基类中调用方法来直接处理对应的事件(方法在下面事件处理器类中说明)
    • 共有9个事件

(2)文件系统事件处理的类

  • import watchdog.events.FileSystemEventHandler(或者from watchdog.events import FileSystemEventHandler)是事件处理器的基类,用于处理事件。在该类中定义的方法有:
  • 以下这些方法中都可以使用event的属性(event.is_directory、event.src_path、event.dest_path)
    • on_moved(self,event):处理DirMovedEvent和FileMovedEvent事件
    • on_created(self,event):处理DirCreatedEvent和FileCreatedEvent事件
    • on_deleted(self,event):处理DirDeletedEvent和FileDeletedEvent事件
    • on_modified(self,event):处理DirModifiedEvent和FileModifiedEvent事件
    • on_closed(self,event):处理FileClosedEvent事件
    • 特殊方法:dispathch(self,event)会优先执行该方法,然后将事件分派给其他方法处理
    • 特殊方法:on_any_event(self,event)该方法会处理任意事件
  • 监控特定文件类型的文件处理类支持正则:from watchdog.events import PatternMatchingEventHandler和RegexMatchingEventHandler 这两个类的父类都是FileSystemEventHandler

(3)观察者类

  • 模块调用方式import watchdog.observers.Observer(或者from watchdog.observers import Observer)该类用于定义观察者线程
  • 其中schedule(event_handler,path,recursive=False)方法非常重要,该方法用于安排要监控的目录,并指定事件处理器以响应文件系统事件(一个观察者observer对象可以多次使用schedule()方法来监控文件系统,这样可以监控多个目录,对每个目录使用不同策略)
    • event_handler参数表示事件处理器的实例
    • path参数表示将要监控的目录路径
    • recursive参数指定是否遍历子目录(True表示遍历)

12.2 实用案例

通用的文件系统更改监控程序:

#!/usr/bin/python3
#_*_coding:utf-8_*_


import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler  #内置的事件处理器的基类

"""定义事件处理器类,调用内置事件处理器"""
class MyHandler(FileSystemEventHandler):
    """定义要处理的事件方法"""
    def on_created(self,event):
        if event.is_directory:
            return
        print(f'{event.src_path} 文件被创建')

    def on_deleted(self,event):
        if event.is_directory:
            return
        print(f'{event.src_path} 文件被删除')
    
    def on_modified(self,event):
        if event.is_directory:
            return
        print(f'{event.src_path}文件被修改')
    
    def on_moved(self, event):
        pass

    def on_closed(self, event):
        pass

    
if __name__ == '__main__':
    path = '.'
    event_handler = MyHandler() #实例化事件处理器
    observer = Observer()   #创建观察者对象,实例化
    observer.schedule(event_handler,path,recursive=True)    #注册事件处理器
    observer.start()    #启动线程
    #维持主线程运行直至强行中断程序
    try:
        while True:
            time.sleep(1)	#保证监听帧率(暂停1秒)
    except KeyboardInterrupt:	#发生键盘中断异常才会停止监听
        observer.stop()
    #主线程结束后,进入阻塞状态,一直等待其他子线程执行结束后再终止
    observer.join()

监控特定文件类型的文件更改程序:

#!/usr/bin/python3
#_*_coding:utf-8_*_


import time
import sys
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler

"""定义事件处理器类,调用内置事件处理器"""
class MyHandler(PatternMatchingEventHandler):
    patterns = ['*.txt','*.py']
    ignore_directories = True	#忽视目录
    
    def on_created(self,event):
        print(f'{event.src_path}被创建')

if __name__ == '__main__':
    #被监控目录由命令行参数指定,如果未指定则监控当前目录
    path = sys.argv[1] if len(sys.argv) > 1 else '.'
    event_handler = MyHandler() #实例化事件处理器
    observer = Observer()   #创建观察者对象,实例化
    observer.schedule(event_handler,path,recursive=True)    #注册事件处理器
    observer.start()    #启动线程
    #维持主线程运行直至强行中断程序
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    #主线程结束后,进入阻塞状态,一直等待其他子线程执行结束后再终止
    observer.join()

自动备份新上传的文件:

#!/usr/bin/python3
#_*_coding:utf-8_*_


import time
import sys
import os
import subprocess
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

"""定义事件处理器类,调用内置事件处理器"""
class MyHandler(FileSystemEventHandler):  
    def __init__(self) -> None:
        super().__init__()
    def on_created(self,event):
        if not event.is_directory:
            bak_file(event.src_path)

def bak_file(src):
    if not os.path.isdir("/bak/"):
        dir = subprocess.run("mkdir -pv /bak/",shell=True,
                             stdout=subprocess.PIPE,encoding='utf-8')
        if dir.returncode == 0:
            print(dir.stdout)
    p = subprocess.Popen(f"cp {src} /bak/",shell=True,stdout=subprocess.PIPE)
    p.communicate()
    if p.returncode == 0:   #returncode==0则表示subprocess运行成功
        print("备份上传文件: ",src)
if __name__ == '__main__':
    #被监控目录由命令行参数指定,如果未指定则监控当前目录
    path = sys.argv[1] if len(sys.argv) > 1 else '.'
    event_handler = MyHandler() #实例化事件处理器
    observer = Observer()   #创建观察者对象,实例化
    observer.schedule(event_handler,path,recursive=True)    #注册事件处理器
    observer.start()    #启动线程

    #维持主线程运行直至强行中断程序
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    #主线程结束后,进入阻塞状态,一直等待其他子线程执行结束后再终止
    observer.join()
posted @   逃离这世界~  阅读(24)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示

目录导航