在python中文件监控主要有两个库:pyinotify依赖于Linux平台的inotify,Linux平台推荐使用此模块,功能比watchdog强大且全面、watchdog。
watchdog模块
主要有3个角色:observer、event_handler、被监控的文件夹。三者原本是独立的,主要通过observer.schedule函数将三者串起来,observer不断检测调用平台依赖代码对监控文件夹进行变动检测,当发现改变时,通知event_handler处理。
watchdog的3个角色
- Observer
主要作用是当作启动和关闭监控程序,给予文件夹路径后,Observer会监控文件夹的变化并且反馈变化。
使用from watchdog.observers import Observer命令导入。 - events
watchdog的动作模块,具体作用是根据Observer模块反馈的事件分配不一样的操作动作方法,然后程序再继承这个方法开始执行所需的代码。
使用from watchdog.events import *命令导入。 - 监控文件夹路径
 
代码实例
# 本模块的功能:<检测文件或目录变化>
# 导入watchdog对应模块
from watchdog.observers import Observer
from watchdog.events import *
# 导入时间模块
import time
class FileEventHandler(FileSystemEventHandler):
    # 初始化
    def __init__(self):
        FileSystemEventHandler.__init__(self)
    # 移动目录或文件
    def on_moved(self, event):
        now=time.strftime("%Y-%m-%d %H:%M;%S",time.localtime())
        if event.is_directory:
            print(f"{now} 移动目录从{event.src_path}到{event.dest_path}")
        else:
            print(f"{now} 移动文件从{event.src_path}到{event.dest_path}")
    # 创建目录或文件
    def on_created(self, event):
        now=time.strftime("%Y-%m-%d %H:%M;%S",time.localtime())
        if event.is_directory:
            print(f"{now} 创建目录{event.src_path}")
        else:
            print(f"{now} 创建文件{event.src_path}")
    # 删除目录或文件
    def on_deleted(self, event):
        now=time.strftime("%Y-%m-%d %H:%M;%S",time.localtime())
        if event.is_directory:
            print("{now} 删除目录{0}".format(event.src_path))
        else:
            print("{now} 删除文件{0}".format(event.src_path))
    # 修改目录或文件
    def on_modified(self, event):
        now=time.strftime("%Y-%m-%d %H:%M;%S",time.localtime())
        if event.is_directory:
            print("{now} 修改目录{0}".format(event.src_path))
        else:
            print("{now} 修改文件{0}".format(event.src_path))
if __name__ == "__main__":
    # 实例化Observer对象
    observer = Observer()
    event_handler = FileEventHandler()
    # 设置监听目录
    dis_dir = "F:\迅雷下载"
    observer.schedule(event_handler,dis_dir,recursive=True) # recursive=True,可以直接写True,表示递归子目录
    print(f"监控目录 {dis_dir}")
    observer.start()
    # try:
    #     while True:
    #         # 设置监听频率(间隔周期时间)
    #         time.sleep(1)
    # except KeyboardInterrupt:
    #     observer.stop()
    observer.join()
pyinotify模块
依赖于Linux内核的inotify功能,inotify是一个事件驱动的通知器,其通知接口从内核空间到用户空间通过三个系统调用。
Notifier是pyinotify模块最重要的类,用来读取通知和处理事件,默认情况下,Notifier处理事件的方式是打印事件。
Notifier类在初始化时接受多个参数,但是只有WatchManager对象是必须传递的参数,WatchManager对象保存了需要监视的文件和目录,以及监视文件和目录的哪些事件,Notifier类根据WatchManager对象中的配置来决定如何处理事件。
#!/usr/bin/env python3
 
import pyinotify
# 创建WatchManager对象 
wm = pyinotify.WatchManager()
# 添加要监控的目录,以及要监控的事件,这里ALL_EVENT表示所有事件         
wm.add_watch('/tmp',pyinotify.ALL_EVENTS)  
# 交给Notifier进行处理
notifier = pyinotify.Notifier(wm)
# 循环处理事件      
notifier.loop()                            
事件标志
下面列举的是事件标志位,可以用'与'来关联监控多个事件,例如multi_event = pyinotify.IN_OPEN | pyinotify.IN_CLOSE_NOWRITE
- IN_ACCESS
被监控项目或者被监控目录中的文件被访问,比如一个文件被读取 - IN_MODIFY	
被监控项目或者被监控目录中的文件被修改 - IN_ATTRIB	
被监控项目或者被监控目录中的文件的属性被修改 - IN_CLOSE_WRITE	
一个可写的文件或者目录被关闭 - IN_CLOSE_NOWRITE	
一个只读的文件或者目录被关闭 - IN_OPEN	
文件或者目录被打开 - IN_MOVED_FROM	
被监控项目或者目录中的文件被移除监控区域 - IN_MOVED_TO	
文件或目录被移入监控区域 - IN_MOVE_SELF
自移动,即一个可执行文件在执行时移动自己 - IN_CREATE	
在所监控的目录中创建子目录或文件 - IN_DELETE	
在所监控的目录中删除目录或文件 - IN_DELETE_SELF
自删除,即一个可执行文件在执行时删除自己 - IN_CLOSE
文件被关闭,等同于(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) - IN_MOVE	
文件被移动,等同于(IN_MOVED_FROM | IN_MOVED_TO) - IN_UNMOUNT
宿主文件系统被umount 
事件处理
前面的例子,我们使用的都是默认的事件处理方式:打印在屏幕上,而很多情况下我们需要定制事件的处理方式,来实现特殊的功能。定制事件需要继承ProcessEvent类,针对需要处理的事件编写process_事件名(self,event)函数即可
import pyinotify
 
 # 监控多个事件:文件被打开或者只读文件被关闭
multi_event = pyinotify.IN_OPEN | pyinotify.IN_CLOSE_NOWRITE
# 创建WatchManager对象
wm = pyinotify.WatchManager()                                   
 
 # 定制化事件处理类,注意继承
class MyEventHandler(pyinotify.ProcessEvent): 
    # 必须为process_事件名称,event表示事件对象                  
    def process_IN_OPEN(self,event): 
        # event.pathname 表示触发事件的文件路径                         
        print('OPEN',event.pathname)                            
    def process_IN_CLOSE_NOWRITE(self,event):
        print('CLOSE_NOWRITE',event.pathname)
# 实例化我们定制化后的事件处理类
handler = MyEventHandler() 
# 在notifier实例化时传入,notifier会自动执行                                     
notifier = pyinotify.Notifier(wm,handler)                       
# 添加监控的目录及事件
wm.add_watch('/tmp',multi_event)                                
notifier.loop()