Statistics
| Branch: | Tag: | Revision:

root / ci / filelocker.py @ 4a23280d

History | View | Annotate | Download (3.1 kB)

1 4b61ee63 Ilias Tsitsimpis
# filelocker.py - Cross-platform (posix/nt) API for flock-style file locking.
2 4b61ee63 Ilias Tsitsimpis
#                 Requires python 1.5.2 or better.
3 4b61ee63 Ilias Tsitsimpis
"""Cross-platform (posix/nt) API for flock-style file locking.
4 4b61ee63 Ilias Tsitsimpis

5 4b61ee63 Ilias Tsitsimpis

6 4b61ee63 Ilias Tsitsimpis
Synopsis:
7 4b61ee63 Ilias Tsitsimpis

8 4b61ee63 Ilias Tsitsimpis
    import filelocker
9 4b61ee63 Ilias Tsitsimpis
    with filelocker.lock("lockfile", filelocker.LOCK_EX):
10 4b61ee63 Ilias Tsitsimpis
        print "Got it"
11 4b61ee63 Ilias Tsitsimpis

12 4b61ee63 Ilias Tsitsimpis

13 4b61ee63 Ilias Tsitsimpis
Methods:
14 4b61ee63 Ilias Tsitsimpis

15 4b61ee63 Ilias Tsitsimpis
   lock ( file, flags, tries=10 )
16 4b61ee63 Ilias Tsitsimpis

17 4b61ee63 Ilias Tsitsimpis

18 4b61ee63 Ilias Tsitsimpis
Constants:
19 4b61ee63 Ilias Tsitsimpis

20 4b61ee63 Ilias Tsitsimpis
   LOCK_EX
21 4b61ee63 Ilias Tsitsimpis
   LOCK_SH
22 4b61ee63 Ilias Tsitsimpis
   LOCK_NB
23 4b61ee63 Ilias Tsitsimpis

24 4b61ee63 Ilias Tsitsimpis

25 4b61ee63 Ilias Tsitsimpis
Exceptions:
26 4b61ee63 Ilias Tsitsimpis

27 4b61ee63 Ilias Tsitsimpis
    LockException
28 4b61ee63 Ilias Tsitsimpis

29 4b61ee63 Ilias Tsitsimpis

30 4b61ee63 Ilias Tsitsimpis
Notes:
31 4b61ee63 Ilias Tsitsimpis

32 4b61ee63 Ilias Tsitsimpis
For the 'nt' platform, this module requires the Python Extensions for Windows.
33 4b61ee63 Ilias Tsitsimpis
Be aware that this may not work as expected on Windows 95/98/ME.
34 4b61ee63 Ilias Tsitsimpis

35 4b61ee63 Ilias Tsitsimpis

36 4b61ee63 Ilias Tsitsimpis
History:
37 4b61ee63 Ilias Tsitsimpis

38 4b61ee63 Ilias Tsitsimpis
I learned the win32 technique for locking files from sample code
39 4b61ee63 Ilias Tsitsimpis
provided by John Nielsen <nielsenjf@my-deja.com> in the documentation
40 4b61ee63 Ilias Tsitsimpis
that accompanies the win32 modules.
41 4b61ee63 Ilias Tsitsimpis

42 4b61ee63 Ilias Tsitsimpis

43 4b61ee63 Ilias Tsitsimpis
Author: Jonathan Feinberg <jdf@pobox.com>,
44 4b61ee63 Ilias Tsitsimpis
        Lowell Alleman <lalleman@mfps.com>
45 4b61ee63 Ilias Tsitsimpis
Version: $Id: filelocker.py 5474 2008-05-16 20:53:50Z lowell $
46 4b61ee63 Ilias Tsitsimpis

47 4b61ee63 Ilias Tsitsimpis

48 4b61ee63 Ilias Tsitsimpis
Modified to work as a contextmanager
49 4b61ee63 Ilias Tsitsimpis

50 4b61ee63 Ilias Tsitsimpis
"""
51 4b61ee63 Ilias Tsitsimpis
52 4b61ee63 Ilias Tsitsimpis
import os
53 4b61ee63 Ilias Tsitsimpis
from contextlib import contextmanager
54 4b61ee63 Ilias Tsitsimpis
55 4b61ee63 Ilias Tsitsimpis
56 4b61ee63 Ilias Tsitsimpis
class LockException(Exception):
57 4b61ee63 Ilias Tsitsimpis
    # Error codes:
58 4b61ee63 Ilias Tsitsimpis
    LOCK_FAILED = 1
59 4b61ee63 Ilias Tsitsimpis
60 4b61ee63 Ilias Tsitsimpis
61 4b61ee63 Ilias Tsitsimpis
# Import modules for each supported platform
62 4b61ee63 Ilias Tsitsimpis
if os.name == 'nt':
63 4b61ee63 Ilias Tsitsimpis
    import win32con
64 4b61ee63 Ilias Tsitsimpis
    import win32file
65 4b61ee63 Ilias Tsitsimpis
    import pywintypes
66 4b61ee63 Ilias Tsitsimpis
    LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
67 4b61ee63 Ilias Tsitsimpis
    LOCK_SH = 0  # the default
68 4b61ee63 Ilias Tsitsimpis
    LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
69 4b61ee63 Ilias Tsitsimpis
    # is there any reason not to reuse the following structure?
70 4b61ee63 Ilias Tsitsimpis
    __overlapped = pywintypes.OVERLAPPED()
71 4b61ee63 Ilias Tsitsimpis
elif os.name == 'posix':
72 4b61ee63 Ilias Tsitsimpis
    import fcntl
73 4b61ee63 Ilias Tsitsimpis
    LOCK_EX = fcntl.LOCK_EX
74 4b61ee63 Ilias Tsitsimpis
    LOCK_SH = fcntl.LOCK_SH
75 4b61ee63 Ilias Tsitsimpis
    LOCK_NB = fcntl.LOCK_NB
76 4b61ee63 Ilias Tsitsimpis
else:
77 4b61ee63 Ilias Tsitsimpis
    raise RuntimeError("FileLocker only defined for nt and posix platforms")
78 4b61ee63 Ilias Tsitsimpis
79 4b61ee63 Ilias Tsitsimpis
80 4b61ee63 Ilias Tsitsimpis
# --------------------------------------
81 4b61ee63 Ilias Tsitsimpis
# Implementation for NT
82 4b61ee63 Ilias Tsitsimpis
if os.name == 'nt':
83 4b61ee63 Ilias Tsitsimpis
    @contextmanager
84 4b61ee63 Ilias Tsitsimpis
    def lock(filename, flags):
85 4b61ee63 Ilias Tsitsimpis
        file = open(filename, "w+")
86 4b61ee63 Ilias Tsitsimpis
        hfile = win32file._get_osfhandle(file.fileno())
87 4b61ee63 Ilias Tsitsimpis
88 4b61ee63 Ilias Tsitsimpis
        try:
89 4b61ee63 Ilias Tsitsimpis
            win32file.LockFileEx(hfile, flags, 0, -0x10000, __overlapped)
90 4b61ee63 Ilias Tsitsimpis
            try:
91 4b61ee63 Ilias Tsitsimpis
                yield
92 4b61ee63 Ilias Tsitsimpis
            finally:
93 4b61ee63 Ilias Tsitsimpis
                file.close()
94 4b61ee63 Ilias Tsitsimpis
        except pywintypes.error, exc_value:
95 4b61ee63 Ilias Tsitsimpis
            # error: (33, 'LockFileEx',
96 4b61ee63 Ilias Tsitsimpis
            #         'The process cannot access the file because another
97 4b61ee63 Ilias Tsitsimpis
            #          process has locked a portion of the file.')
98 4b61ee63 Ilias Tsitsimpis
            file.close()
99 4b61ee63 Ilias Tsitsimpis
            if exc_value[0] == 33:
100 4b61ee63 Ilias Tsitsimpis
                raise LockException(LockException.LOCK_FAILED, exc_value[2])
101 4b61ee63 Ilias Tsitsimpis
            else:
102 4b61ee63 Ilias Tsitsimpis
                # Q:  Are there exceptions/codes we should be dealing with?
103 4b61ee63 Ilias Tsitsimpis
                raise
104 4b61ee63 Ilias Tsitsimpis
105 4b61ee63 Ilias Tsitsimpis
106 4b61ee63 Ilias Tsitsimpis
# --------------------------------------
107 4b61ee63 Ilias Tsitsimpis
# Implementation for Posix
108 4b61ee63 Ilias Tsitsimpis
elif os.name == 'posix':
109 4b61ee63 Ilias Tsitsimpis
    @contextmanager
110 4b61ee63 Ilias Tsitsimpis
    def lock(filename, flags):
111 4b61ee63 Ilias Tsitsimpis
        file = open(filename, "w+")
112 4b61ee63 Ilias Tsitsimpis
113 4b61ee63 Ilias Tsitsimpis
        try:
114 4b61ee63 Ilias Tsitsimpis
            fcntl.flock(file.fileno(), flags)
115 4b61ee63 Ilias Tsitsimpis
            try:
116 4b61ee63 Ilias Tsitsimpis
                yield
117 4b61ee63 Ilias Tsitsimpis
            finally:
118 4b61ee63 Ilias Tsitsimpis
                file.close()
119 4b61ee63 Ilias Tsitsimpis
        except IOError, exc_value:
120 4b61ee63 Ilias Tsitsimpis
            #  IOError: [Errno 11] Resource temporarily unavailable
121 4b61ee63 Ilias Tsitsimpis
            file.close()
122 4b61ee63 Ilias Tsitsimpis
            if exc_value[0] == 11:
123 4b61ee63 Ilias Tsitsimpis
                raise LockException(LockException.LOCK_FAILED, exc_value[1])
124 4b61ee63 Ilias Tsitsimpis
            else:
125 4b61ee63 Ilias Tsitsimpis
                raise