Statistics
| Branch: | Tag: | Revision:

root / ci / filelocker.py @ 9f41ab1e

History | View | Annotate | Download (3.1 kB)

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

5 62fcf0e5 Ilias Tsitsimpis

6 62fcf0e5 Ilias Tsitsimpis
Synopsis:
7 62fcf0e5 Ilias Tsitsimpis

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

12 62fcf0e5 Ilias Tsitsimpis

13 62fcf0e5 Ilias Tsitsimpis
Methods:
14 62fcf0e5 Ilias Tsitsimpis

15 62fcf0e5 Ilias Tsitsimpis
   lock ( file, flags, tries=10 )
16 62fcf0e5 Ilias Tsitsimpis

17 62fcf0e5 Ilias Tsitsimpis

18 62fcf0e5 Ilias Tsitsimpis
Constants:
19 62fcf0e5 Ilias Tsitsimpis

20 62fcf0e5 Ilias Tsitsimpis
   LOCK_EX
21 62fcf0e5 Ilias Tsitsimpis
   LOCK_SH
22 62fcf0e5 Ilias Tsitsimpis
   LOCK_NB
23 62fcf0e5 Ilias Tsitsimpis

24 62fcf0e5 Ilias Tsitsimpis

25 62fcf0e5 Ilias Tsitsimpis
Exceptions:
26 62fcf0e5 Ilias Tsitsimpis

27 62fcf0e5 Ilias Tsitsimpis
    LockException
28 62fcf0e5 Ilias Tsitsimpis

29 62fcf0e5 Ilias Tsitsimpis

30 62fcf0e5 Ilias Tsitsimpis
Notes:
31 62fcf0e5 Ilias Tsitsimpis

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

35 62fcf0e5 Ilias Tsitsimpis

36 62fcf0e5 Ilias Tsitsimpis
History:
37 62fcf0e5 Ilias Tsitsimpis

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

42 62fcf0e5 Ilias Tsitsimpis

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

47 62fcf0e5 Ilias Tsitsimpis

48 62fcf0e5 Ilias Tsitsimpis
Modified to work as a contextmanager
49 62fcf0e5 Ilias Tsitsimpis

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