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