1
2
3
4
5
6
7 """
8 Cross-platform (posix/nt) API for flock-style file locking.
9
10 Synopsis:
11
12 import portalocker
13 file = open(\"somefile\", \"r+\")
14 portalocker.lock(file, portalocker.LOCK_EX)
15 file.seek(12)
16 file.write(\"foo\")
17 file.close()
18
19 If you know what you're doing, you may choose to
20
21 portalocker.unlock(file)
22
23 before closing the file, but why?
24
25 Methods:
26
27 lock( file, flags )
28 unlock( file )
29
30 Constants:
31
32 LOCK_EX
33 LOCK_SH
34 LOCK_NB
35
36 I learned the win32 technique for locking files from sample code
37 provided by John Nielsen <nielsenjf@my-deja.com> in the documentation
38 that accompanies the win32 modules.
39
40 Author: Jonathan Feinberg <jdf@pobox.com>
41 Version: $Id: portalocker.py,v 1.3 2001/05/29 18:47:55 Administrator Exp $
42 """
43
44 import logging
45 import platform
46 logger = logging.getLogger("web2py")
47
48 os_locking = None
49 try:
50 import google.appengine
51 os_locking = 'gae'
52 except:
53 try:
54 import fcntl
55 os_locking = 'posix'
56 except:
57 try:
58 import win32con
59 import win32file
60 import pywintypes
61 os_locking = 'windows'
62 except:
63 pass
64
65 if os_locking == 'windows':
66 LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
67 LOCK_SH = 0
68 LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
69
70
71
72 __overlapped = pywintypes.OVERLAPPED()
73
74 - def lock(file, flags):
75 hfile = win32file._get_osfhandle(file.fileno())
76 win32file.LockFileEx(hfile, flags, 0, 0x7fff0000, __overlapped)
77
79 hfile = win32file._get_osfhandle(file.fileno())
80 win32file.UnlockFileEx(hfile, 0, 0x7fff0000, __overlapped)
81
82
83 elif os_locking == 'posix':
84 LOCK_EX = fcntl.LOCK_EX
85 LOCK_SH = fcntl.LOCK_SH
86 LOCK_NB = fcntl.LOCK_NB
87
88 - def lock(file, flags):
89 fcntl.flock(file.fileno(), flags)
90
92 fcntl.flock(file.fileno(), fcntl.LOCK_UN)
93
94
95 else:
96 if platform.system() == 'Windows':
97 logger.error('no file locking, you must install the win32 extensions from: http://sourceforge.net/projects/pywin32/files/')
98 elif os_locking != 'gae':
99 logger.debug('no file locking, this will cause problems')
100
101 LOCK_EX = None
102 LOCK_SH = None
103 LOCK_NB = None
104
105 - def lock(file, flags):
107
110
111
113 - def __init__(self, filename, mode='rb'):
114 self.filename = filename
115 self.mode = mode
116 self.file = None
117 if 'r' in mode:
118 self.file = open(filename, mode)
119 lock(self.file, LOCK_SH)
120 elif 'w' in mode or 'a' in mode:
121 self.file = open(filename, mode.replace('w', 'a'))
122 lock(self.file, LOCK_EX)
123 if not 'a' in mode:
124 self.file.seek(0)
125 self.file.truncate()
126 else:
127 raise RuntimeError("invalid LockedFile(...,mode)")
128
129 - def read(self, size=None):
131
134
137
141
143 if not self.file is None:
144 unlock(self.file)
145 self.file.close()
146 self.file = None
147
149 if not self.file is None:
150 self.close()
151
152
158
159
164
165 if __name__ == '__main__':
166 f = LockedFile('test.txt', mode='wb')
167 f.write('test ok')
168 f.close()
169 f = LockedFile('test.txt', mode='rb')
170 sys.stdout.write(f.read()+'\n')
171 f.close()
172