Skip to content
Niko Ehrenfeuchter edited this page Jun 30, 2015 · 6 revisions

Subclassing ProcessEvent

We can subclass ProcessEvent and provide our own event handler by defining appropriate methods. See the commented example below:

import pyinotify

class MyEventHandler(pyinotify.ProcessEvent):
    def my_init(self, file_object=sys.stdout):
        """
        This is your constructor it is automatically called from
        ProcessEvent.__init__(), And extra arguments passed to __init__() would
        be delegated automatically to my_init().
        """
        self._file_object = file_object

    def process_IN_DELETE(self, event):
        """
        This method processes a specific type of event: IN_DELETE. event
        is an instance of Event.
        """
        self._file_object.write('deleting: %s\n' % event.pathname)

    def process_IN_CLOSE(self, event):
        """
        This method is called on these events: IN_CLOSE_WRITE and
        IN_CLOSE_NOWRITE.
        """
        self._file_object.write('closing: %s\n' % event.pathname)

    def process_default(self, event):
        """
        Eventually, this method is called for all others types of events.
        This method can be useful when an action fits all events.
        """
        self._file_object.write('default processing\n')

# A way to instantiate this class could be:
p = MyEventHandler(file('/tmp/output', 'w'))

Explanations and details:

  • IN_DELETE has a specific method. An individual processing method is provided by a method whose the name is written with a specific syntax: process_EVENT_NAME where EVENT_NAME is the name of the current event to process.
  • Related events most of the time need the same treatment. In those cases shared methods can be defined avoiding duplicating chunks of codes. Like for instance for those two following related events:
      mask = pyinotify.IN_CLOSE_WRITE | pyinotify.IN_CLOSE_NOWRITE

It is enough to implement a method named process_IN_CLOSE (according to pattern process_IN_FAMILYBASENAME) to handle both types of events. Beware though, not to also implement process_IN_CLOSE_WRITE or process_IN_CLOSE_NOWRITE, because if defined these methods would have an higher precedence (see below) over process_IN_CLOSE and the latter would not be called.

  • ALL_EVENTS isn't an event by itself, it is the aggregation of all events codes, that means that you can't implement the method process_ALL_EVENTS.
  • If we need to apply a single treatment whatever the kind of event received or if we need to have a fall back method for unexpected events, we just need to implement process_default which is the default method.
  • Processing methods lookup's order (by increasing order of priority): specialized methods (eg: process_IN_CLOSE_WRITE) first, then family methods (eg: process_IN_CLOSE), finally default method process_default.
  • One more thing: say you redefine the method process_default which contains the instruction os.ismount(my-mount-point), it would be for example a mistake having this method called for every event IN_OPEN occurring on /etc. Because, one particularity of os.ismount is to check in /etc/mtab if the partition is mounted, in this case it would lead to an endless situation: process_IN_OPEN called, /etc/mtab opened, process_IN_OPEN called, /etc/mtab opened... looping forever.

Whenever possible you should process your notifications this way:

notifier = pyinotify.Notifier(wm, MyEventHandler())

But, some watches may need a different kind of processing, you can attach them a specialized instance which will be called only on their associated watch:

wm.add_watch('/one/path', pyinotify.ALL_EVENTS, proc_fun=MyEventHandler())
Clone this wiki locally