As you know Linux provides the inotify(7) API to monitor file system events using a convenient system calls that allows you to retrieve information about file system changes. The system calls that provides that API are implemented in a wide variety of high level programming languages, such as Python, Perl, and others. The Python implementation to wrap those calls has at least three variants, so I will review each of them in this article.
The two well known variants of the inotify(7) API for Python are inotifyx and pyinotify. The most complete file system notification API is provided by the pyinotify Python package.
The inotifyx interface provides a simple function based API, with an object wrapper for event objects through the InotifyEvent class. It lacks a main loop for event notifications, so you need to create the event loop by your own. Also it is small and simple, do not requires too much knowledge of the notification API.
So, the best option for me is the pyinotify interface, which provides full integration with the file system event API, so you can track with those events with a full object oriented implementation where you can handle any kind of events over files and directories. One of my recent projects is a log monitor daemon that integrates file system monitoring tasks to log storage on a RDBMS engine. Each time that a log is written, it examines the remaining lines from the current offset to the end of the file that has been written, and extracts the log entries to be stored on the RDBMS. The event chosen to be handled in this case is the IN_CLOSE_WRITE event, which indicates that the directory has suffered a file writes and file close events.
class WatchLogProceesing(pyinotify.ProcessEvent): """ This class is a monitor for those files that are placed on the log directory. Once the system writes those system and closes them, this class notifies to its handler to process the event. """ def process_IN_CLOSE_WRITE(self, event): """ Process the close/write event. """ daemon_log("%s: processing %s" % (s.argv[0], event.pathname)) process_input(event.pathname) def monitor_dir(directory): """ Starts monitoring a directory for changes using the pyinotify API """ try: wmn = pyinotify.WatchManager() notifier = pyinotify.Notifier(wmn, WatchLogProceesing()) wmn.add_watch(directory, pyinotify.IN_CLOSE_WRITE) notifier.loop() except Exception, exc: print(str(exc)) print(format_exc(exc))
The notifier.loop() call, means that the notifier will enter in an event loop handler, catching all included events in the WatchManager.add_watch() call. This API is very similar to the BSD Kqueue interface, but less complete, since inotify(7) only can handle file system events, and kqueue(2) can handle file descriptor events, so you can apply kqueue system calls to sockets and related stuff, making of kqueue more universal system calls for file descriptor events. Try playing with both, kqueue and inotify API, you will find it interesting :)