pythonpyinotify

enabling start, stop feature for a folder watcher program


The code below doesn't work like I want it to. When I do svc.run() the programs runs okay. Any changes I've made to my folder works file. But when I do svc.stop() it doesn't exactly stop I think. Perhaps there must be a better way of doing the threading part...

import pyinotify
import threading
import time
import os
class fs_event_handler(pyinotify.ProcessEvent):
    def __init__(self, callback):
        self._callback = callback
    def process_IN_CREATE(self, e):
        self._callback(e.path, e.name, 'created')
    def process_IN_DELETE(self, e):
        self._callback(e.path, e.name, 'deleted')
    def process_IN_MODIFY(self, e):
        self._callback(e.path, e.name, 'modified')

class NotificationService():
    def __init__(self, path, callback):
        mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE \
            | pyinotify.IN_MODIFY
        w = pyinotify.WatchManager()
        self.__notifier = pyinotify.Notifier(w, fs_event_handler(callback))
        wdd = w.add_watch(path, mask, rec=True, auto_add=True)
        self.__loop = True
    def start(self):
        while self.__loop:
            self.__notifier.process_events()
            if self.__notifier.check_events():
                self.__notifier.read_events()
    def run(self):
        fm = FileMonitor(self)
        fm.start()
        print 'Service Running...'

    def stop(self):
        self.__notifier.stop()
        self.__loop = False

class FileMonitor(threading.Thread):
    def __init__(self, srvc):
        threading.Thread.__init__(self)
        self.__svc = srvc
    def run(self):
        self.__svc.start()
        print 'Service stopped'

def _callback(path, name, operation):
    zpad = lambda x: ''.join(['0', str(x)])[:2]
    ts = time.localtime()
    t = ':'.join(map(zpad, [ts.tm_hour, ts.tm_min, ts.tm_sec]))
    print t, ':', '%s was %s' % (os.path.join(path, name), operation)


p = '/home/deostroll/scripts/tmp'
svc = NotificationService(p, _callback)
svc.run()

Solution

  • I'm not familiar with pyinorify, but it seems that self.__notifier.process_events() blocks so self.__loop doesn't get read until some event happens.

    You can just use pyinotify.ThreadedNotifier instead:

    class NotificationService():
        def __init__(self, path, callback):
            self.path = path
            self.callback = callback
    
        def start(self):
            mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE \
                | pyinotify.IN_MODIFY
            w = pyinotify.WatchManager()
            wdd = w.add_watch(self.path, mask, rec=True, auto_add=True)
            self.__notifier = pyinotify.ThreadedNotifier(w, fs_event_handler(self.callback))
            self.__notifier.start()
            print 'Service Running...'
    
        def run(self):
            self.start()
    
        def stop(self):
            self.__notifier.stop()
            print 'Service Stopped'