0

I've written simple script to update my CSS styles (from less to css) every time when i change less file. I have now:

import time
import hashlib
from subprocess import call


def md5_checksum(filePath):
    fh = open(filePath, 'rb')
    m = hashlib.md5()
    m.update(fh.read())
    fh.close()
    return m.hexdigest()

md5 = md5_checksum('styles.less')

while True:
    newmd5 = md5_checksum('styles.less')
    if md5 != newmd5:
        sh = open('styles.css', 'w')
        call(['lessc', 'styles.less'], stdout=sh)
        md5 = newmd5
        sh.close()
        print 'Changed'
    time.sleep(0.2)

And what is strange, script is working for some time:

Changed
Changed
Changed
Changed
Traceback (most recent call last):
  File "watcher.py", line 16, in <module>
    newmd5 = md5_checksum('styles.less')
  File "watcher.py", line 7, in md5_checksum
    fh = open(filePath, 'rb')
IOError: [Errno 2] No such file or directory: 'styles.less'

Whats going on? File is still there for 100%. What am i doing wrong?

tshepang
  • 12,111
  • 21
  • 91
  • 136
marxin
  • 3,692
  • 3
  • 31
  • 44
  • 3
    Is the file being replaced my another process? Then you could easily catch the moment where the old entry was removed and the new file isn't available yet! – Martijn Pieters May 24 '13 at 11:12
  • 1
    Probably of interest to you: [How do I watch a file for changes using Python?](http://stackoverflow.com/q/182197) – Martijn Pieters May 24 '13 at 11:13
  • Are you running under Windows? Many antivirus tools interact badly with file system operations. :-( – John Szakmeister May 24 '13 at 11:15
  • jszakmeister: linux. Martijn: File is edited by me in vim. I think that you are right ;) Probably when i press :w in vim, it takes some time for vim to replace that file. It makes sense. Thanks :) – marxin May 24 '13 at 11:22
  • But... how its done? Every file has a creation time. So when file is replaced, creation time should be replaced also? If file is replaced, why creation time doesnt change? If file isnt replaced, why i cant open it for reading? – marxin May 24 '13 at 12:02
  • Assuming that the cause really is that the file is replaced internally rather than overwriten I'd say the creation time doesn't change because the filesystem is smarter than that :) It would know that it's only replacing this file to make changes to it and therefore it would not change the creation time in it's tables. Somehow i don't want to believe that this is actually what happens though. – pypat May 24 '13 at 12:54
  • It seems to, i added try catch IOError -> continue and it works now ;] – marxin May 24 '13 at 12:57

1 Answers1

0

As pointed by Martijn Pieters, when im editing less file in text editor there is some time when file does not exist (during save, when old file is replaced by new file).

Log from strace (strace -o strace.log vim styles.less):

rename("styles.less", "styles.less~")   = 0                               = 0
open("styles.less", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 3
write(3, "@text-color: #000;\n@btn-font-col"..., 1135) = 1135
fsync(3)                                = 0
getxattr("styles.less~", "security.selinux", "unconfined_u:object_r:user_home_t:s0", 255) = 37
getxattr("styles.less", "security.selinux", "unconfined_u:object_r:user_home_t:s0", 255) = 37
stat("styles.less", {st_mode=S_IFREG|0644, st_size=1135, ...}) = 0
stat("styles.less", {st_mode=S_IFREG|0644, st_size=1135, ...}) = 0
close(3)                                = 0
chmod("styles.less", 0100644)           = 0
setxattr("styles.less", "system.posix_acl_access", "\x02\x00\x00\x00\x01\x00\x06\x00\xff\xff\xff\xff\x04\x00\x04\x00\xff\xff\xff\xff \x00\x04\x00\xff\xff\xff\xff", 28, 0) = 0
stat(".../styles.less", {st_mode=S_IFREG|0644, st_size=1135, ...}) = 0
unlink("styles.less~")

So, possible solution is to add:

try:
    ...
catch IOError:
    continue
else:
    ...

Or, even better is to use methods pointed there: How do I watch a file for changes?.

Community
  • 1
  • 1
marxin
  • 3,692
  • 3
  • 31
  • 44