KQueue event notification for Mac OS X
Mac OSX (and all? BSDs) provide a kernel event notification mechanism called kqueue. Other operating systems provide a similar sort of notification system, but OSX’s is the only one I am interested at this time. I did find a rather interesting cross-platform notification library called libevent-python, which attempts to provide a unified API, but it appears to be geared toward network communication and not toward file system notification.
Here’s a BSD-licensed class that can be used to watch a directory. It requires the PyKQueue from hpio.
import osimport kqueueimport sets
class DirectoryChangedException(Exception): pass
class Watch(object): def __init__(self, directory): self.directory = directory self.dirfd = os.open(self.directory, os.O_RDONLY) self.filter = kqueue.EV_ADD|kqueue.EV_CLEAR|kqueue.EV_ENABLE self.event = kqueue.Event(self.dirfd, kqueue.EVFILT_VNODE, self.filter, fflags=kqueue.NOTE_WRITE|\ kqueue.NOTE_DELETE|\ kqueue.NOTE_EXTEND, data=self.dirfd) self.kq = kqueue.kqueue()
def watch(self): self.files = sets.Set(os.listdir(self.directory)) self.adds = None; self.deletes=None; self.changed=None while 1: events = kqueue.kevent(self.kq, [self.event], 10, None) if events: new_files = sets.Set(os.listdir(self.directory)) self.deletes = list(self.files.difference(new_files)) self.adds = list(new_files.difference(self.files)) self.files = new_files raise DirectoryChangedException, \ “Directory %s changed…” % self.directory def __del__(self): os.close(self.dirfd)
One way to use it is as so:
import watchw = watch.Watch('/Users/hobu/foo')
while 1: try: w.watch() except watch.DirectoryChangedException: adds = w.adds deletes = w.deletes print "added files: ", adds print "deleted files: ", deletes