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