Quick start
To familiarize yourself with pyinotify, run a first example like this from the source directory:
$ python pyinotify.py -v # By default watch /tmp for all events $ python pyinotify.py -v my-dir-to-watch # Watch the path my-dir-to-watch for all events
Or if you already have installed pyinotify you should use this command:
$ python -m pyinotify -v $ python -m pyinotify -v my-dir-to-watch
Obviouly my-dir-to-watch must be a path leading to a valid directory. If you go into that directory, and take some actions on its content (read a file...) you should observe new events.
Type this command to visualize all the different options:
$ python pyinotify.py -h
Quick Tutorial
Let's start a more detailed example. Say, we want to monitor the temp directory '/tmp' and all its subdirectories for every new file's creation or deletion. For sake of simplicity, we only print messages for every notification on standart output.
Now you have the choice to receive and process notifications in the main thread (by instantiating Notifier), the drawback is to block your program in this task. Or, if you absolutely want to accomplish others actions you can decide to spawn a new thread (by instatiating ThreadedNotifier) for handling notifications separately. The former method is the preferred one, everything you can do in a new thread can be done in a single one. Moreover the non-threaded implementation has few more functionalities. Next, we will detail the two differents approaches, let's start with the common code
from pyinotify import WatchManager, Notifier, ThreadedNotifier, ProcessEvent, IN_DELETE, IN_CREATE # The watch manager stores the watches and provide operations on watches wm = WatchManager()
The following class inherits from ProcessEvent (the processing base class), it will handle notifications and take actions through specifics processing methods whose the name follows this convention: process_EVENT_TYPE where EVENT_TYPE is the type of event to process.
mask = IN_DELETE | IN_CREATE # watched events class PTmp(ProcessEvent): def process_IN_CREATE(self, event): print "Creating:", event.pathname def process_IN_DELETE(self, event): print "Removing:", event.pathname
Next, we describe respectively the code which instantiate Notifier's class and the threaded code using ThreadedNotifier:
- Class Notifier (see tutorial_notifier.py):
p = PTmp() notifier = Notifier(wm, p) # Internally, p is a callable object and on events p will be used like this: p(new_event)
The next statement add a watch on the first parameter and recursively on all its subdirectories (with rec=True), note that symlinks are not followed. By default, the monitoring is limited to the level of the given directory. It returns a dict where keys are paths and values are corresponding watch descriptors (wd). An unique wd is attributed to every new watch. It is useful (and often necessary) to keep those wds for further updating or removing some of those watches.
wdd = wm.add_watch('/tmp', mask, rec=True)
Start processing the events with this last statement. The call to this method is blocking until we type c-c (sigint)
notifier.loop()
- Class ThreadedNotifier (see tutorial_threadednotifier.py):
notifier = ThreadedNotifier(wm, PTmp()) # Start the notifier from a new thread, without doing anything as no directory or file is being monitored yet. notifier.start() # Start watching a path wdd = wm.add_watch('/tmp', mask, rec=True)
At any moment we can for example remove the watch on '/tmp' like that
if wdd['/tmp'] > 0: # test if the wd is valid, ie. if /tmp is being watched, this test is not mandatory wm.rm_watch(wdd['/tmp'])
Note that its subdirectories (if any) are still being watched. If we wanted to remove '/tmp' and all the watches on its sudirectories, we must proceed like that
wm.rm_watch(wdd['/tmp'], rec=True)
Or even better like that
wm.rm_watch(wdd.values())
That is, most of the code is written, next, we can add, update or remove watches on files or directories with the same principles. The only remaining important task is to stop the thread when we wish stop monitoring
notifier.stop()
Testing it
You can download these two previous examples here tutorial_notifier.py and tutorial_threadednotifier.py
For the first example you can execute it in a console:
$ python tutorial_notifier.py
Then, in another console execute the following commands:
$ touch /tmp/foo && rm -f /tmp/foo
The first console should display now:
Creating: /tmp/foo Removing: /tmp/foo