Using Ken's first example, here's what I came up with: import os import stat from twisted.internet import reactor class FileWatcher: def __init__(self, period, filename): self.period = period self.filename = filename self.callbacks = [] self.mtime = os.stat(filename)[stat.ST_MTIME] reactor.callWhenRunning(self.checkFile) def addCallback(self, callback): self.callbacks.append(callback) def removeCallback(self, callback): self.callbacks.remove(callback) def checkFile(self): mtime = os.stat(self.filename)[stat.ST_MTIME] if mtime > self.mtime: self.mtime = mtime for callback in self.callbacks: callback(self.filename, mtime) reactor.callLater(self.period, self.checkFile) if __name__=='__main__': import time def changed(filename, mtime): print "%s modified at %s." % (filename, time.ctime(mtime)) open('/tmp/foo', "w").close() FileWatcher(0.1, '/tmp/foo').addCallback(changed) reactor.run() Run it in one terminal window, and in the other run touch /tmp/foo to see what happens.