views:

83

answers:

2

Have an example piece of (Python) code to check if a directory has changed:

import os

def watch(path, fdict):
    """Checks a directory and children for changes"""
    changed = []
    for root, dirs, files in os.walk(path):
       for f in files:
           abspath = os.path.abspath(os.path.join(root, f))
           new_mtime = os.stat(abspath).st_mtime
           if not fdict.has_key(abspath) or new_mtime > fdict[abspath]:
               changed.append(abspath)
               fdict[abspath] = new_mtime
    return fdict, changed

But the accompanying unittest randomly fails unless I add at least a 2 second sleep:

import unittest
import project_creator
import os
import time


class tests(unittest.TestCase):
    def setUp(self):
        os.makedirs('autotest')
        f = open(os.path.join('autotest', 'new_file.txt'), 'w')
        f.write('New file')

    def tearDown(self):
        os.unlink(os.path.join('autotest', 'new_file.txt'))
        os.rmdir('autotest')

    def test_amend_file(self):
        changed = project_creator.watch('autotest', {})
        time.sleep(2)
        f = open(os.path.join('autotest', 'new_file.txt'), 'a')
        f.write('\nA change!')
        f.close()
        changed = project_creator.watch('autotest', changed[0])
        self.assertEqual(changed[1], [os.path.abspath(os.path.join('autotest', 'new_file.txt'))])

if __name__ == '__main__':
    unittest.main()

Is stat really limited to worse than 1 second accuracy? (Edit: apparently so, with FAT) Is there any (cross platform) way of detecting more rapid changes?

+1  A: 

The proper way is to watch a directory instead of polling for changes.

Check out FindFirstChangeNotification Function.
Watch a Directory for Changes is a Python implementation.

If directory watching isn't accurate enough then probably the only alternative is to intercept file systems calls.

Nick D
This is something I looked into, but as stated above I need this code to run cross platform (XP and Ubuntu specifically). I may have to give up and vary the mechanism based on os.
mavnn
A: 

if this were linux, i'd use inotify. there's apparently a windows inotify equivalent - the java jnotify library has implemented it - but i don't know if there's a python implementation

Igor
err yea, what Nick D said.
Igor