当前位置: 首页 > 工具软件 > Pyinotify > 使用案例 >

通过pyinotify实现文件的监控,包括监控文件是否传输完成

曾高杰
2023-12-01

首先安装pyinofitypip install pyinotify

创建Event Processor

与linux下面的inotify事件机制类似,我们通过继承ProcessEvent来实现对inotify事件的重写,这里将事件名封装成process_事件名,例如IN_CREATE会经过Event Processor变成process_IN_CREATE。下面是所有的事件:

Inotify EventsDescription
IN_CREATEFile/directory created in watched directory
IN_OPENFile/directory opened in watched directory
IN_ACCESSFile accessed
IN_ATTRIBAttributes of file/directory changed (e.g. permissions, timestamp, etc.)
IN_CLOSE_NOWRITENon-writable file/directory closed
IN_DELETEFile/directory deleted from watched directory
IN_DELETE_SELFFile/directory being watched deleted
IN_IGNOREDFile/directory no longer watched, deleted, or unmounted filesystem
IN_MODIFYFile/directory modified
IN_MOVE_SELFFile/directory moved. Must monitor destination to know destination path
IN_MOVED_FROMFile/directory moved from one watched directory to another
IN_MOVED_TOSimilar to IN_MOVED_FROM except for outgoing file/directory
IN_Q_OVERFLOWEvent queue overflowed
IN_UNMOUNTFilesystem of watched file/directory unmounted from system

下面将通过一个简短的例子来展示:

import os
import pyinotify


class EventProcessor(pyinotify.ProcessEvent):
    _methods = ["IN_CREATE",
                "IN_OPEN",
                "IN_ACCESS",
                "IN_ATTRIB",
                "IN_CLOSE_NOWRITE",
                "IN_CLOSE_WRITE",
                "IN_DELETE",
                "IN_DELETE_SELF",
                "IN_IGNORED",
                "IN_MODIFY",
                "IN_MOVE_SELF",
                "IN_MOVED_FROM",
                "IN_MOVED_TO",
                "IN_Q_OVERFLOW",
                "IN_UNMOUNT",
                "default"]


def process_generator(cls, method):
    def _method_name(self, event):
        print("Method name: process_{}()\n"
              "Path name: {}\n"
              "Event Name: {}\n".format(method, event.pathname, event.maskname))

    _method_name.__name__ = "process_{}".format(method)
    setattr(cls, _method_name.__name__, _method_name)


for method in EventProcessor._methods:
    process_generator(EventProcessor, method)

watch_manager = pyinotify.WatchManager()
event_notifier = pyinotify.Notifier(watch_manager, EventProcessor())

watch_this = os.path.abspath("/home/vincent/software")
watch_manager.add_watch(watch_this, pyinotify.ALL_EVENTS)
event_notifier.loop()

这里我们可以看到,监控了一个文件夹/home/vincent/software,当往这个文件夹中复制一份文件时,将会打印出所有对应的事件。

Method name: process_IN_CREATE()
Path name: /home/vincent/software/Anaconda3-2021.05-Linux-x86_64.sh
Event Name: IN_CREATE

Method name: process_IN_OPEN()
Path name: /home/vincent/software/Anaconda3-2021.05-Linux-x86_64.sh
Event Name: IN_OPEN

Method name: process_IN_MODIFY()
Path name: /home/vincent/software/Anaconda3-2021.05-Linux-x86_64.sh
Event Name: IN_MODIFY

Method name: process_IN_MODIFY()
Path name: /home/vincent/software/Anaconda3-2021.05-Linux-x86_64.sh
Event Name: IN_MODIFY

Method name: process_IN_MODIFY()
Path name: /home/vincent/software/Anaconda3-2021.05-Linux-x86_64.sh
Event Name: IN_MODIFY

Method name: process_IN_CLOSE_WRITE()
Path name: /home/vincent/software/Anaconda3-2021.05-Linux-x86_64.sh
Event Name: IN_CLOSE_WRITE

可以看出来,他会记录下文件操作的每一步,包括文件创建IN_CREATE,文件打开IN_OPEN,文件修改IN_MODIFY,文件关闭IN_CLOSE_WRITE

Non-Blocking Loop非阻塞方式

上面的loop()的方式会阻塞进程,在loop后面的代码将不会被执行,这里有三种解决办法:

Notifier with a timeout 使用超时

在构造notifier时,timeout参数告诉Notifier以特定的时间间隔获取通知。

event_notifier = pyinotify.Notifier(watch_manager, EventProcessor(), timeout=10)

当使用超时时,应用程序将不会自动获得文件系统更改通知。需要在不同的时间显式调用event_notifier.process_events()event_notifier.read_events()。也可以调用event_notifier.check_events()来检查是否有事件等待处理。

ThreadedNotifier不同线程

可以将程序放到另一个线程中,通过ThreadedNotifier而不是Notifier调用,然后通过event_notifier.start()启动

event_notifier = pyinotify.ThreadedNotifier(watch_manager, EventProcessor())

watch_this = os.path.abspath("notification_dir")
watch_manager.add_watch(watch_this, pyinotify.ALL_EVENTS)
event_notifier.start()

AsyncNotifier异步

可以通过异步实现:

event_notifier = pyinotify.AsyncNotifier(watch_manager, EventProcessor())

然后通过调用asyncore中的loop()函数实现:

import asyncore
asyncore.loop()

inotify的局限性也适用于pyinotify。例如,不监视递归目录;必须运行另一个inotify实例来跟踪子目录。尽管Python提供了一个方便的inotify接口,但与C实现的inotify相比,会导致性能下降。

 类似资料: