1 # portalocker.py - Cross-platform (posix/nt) API for flock-style file locking.
2 # Requires python 1.5.2 or better.
4 # ID line added by richard for Roundup file tracking
5 # $Id: portalocker.py,v 1.5 2003-02-20 22:56:49 richard Exp $
7 """ Cross-platform (posix/nt) API for flock-style file locking.
9 Synopsis:
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()
18 If you know what you're doing, you may choose to
20 portalocker.unlock(file)
22 before closing the file, but why?
24 Methods:
26 lock( file, flags )
27 unlock( file )
29 Constants:
31 LOCK_EX
32 LOCK_SH
33 LOCK_NB
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.
39 Author: Jonathan Feinberg <jdf@pobox.com>
40 Version: Id: portalocker.py,v 1.3 2001/05/29 18:47:55 Administrator Exp
41 **un-cvsified by richard so the version doesn't change**
42 """
43 import os
45 if os.name == 'nt':
46 import win32con
47 import win32file
48 import pywintypes
49 LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
50 LOCK_SH = 0 # the default
51 LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
52 # is there any reason not to reuse the following structure?
53 __overlapped = pywintypes.OVERLAPPED()
54 elif os.name == 'posix':
55 import fcntl
56 LOCK_EX = fcntl.LOCK_EX
57 LOCK_SH = fcntl.LOCK_SH
58 LOCK_NB = fcntl.LOCK_NB
59 else:
60 raise RuntimeError("PortaLocker only defined for nt and posix platforms")
62 if os.name == 'nt':
63 def lock(file, flags):
64 hfile = win32file._get_osfhandle(file.fileno())
65 # LockFileEx is not supported on all Win32 platforms (Win95, Win98, WinME).
66 # If it's not supported, win32file will raise an exception.
67 # Try LockFileEx first, as it has more functionality and handles
68 # blocking locks more efficiently.
69 try:
70 win32file.LockFileEx(hfile, flags, 0, 0xffff0000, __overlapped)
71 except win32file.error, e:
72 import winerror
73 # Propagate upwards all exceptions other than not-implemented.
74 if e[0] != winerror.ERROR_CALL_NOT_IMPLEMENTED:
75 raise e
77 # LockFileEx is not supported. Use LockFile.
78 # LockFile does not support shared locking -- always exclusive.
79 # Care: the low/high length params are reversed compared to LockFileEx.
80 if not flags & LOCK_EX:
81 import warnings
82 warnings.warn("PortaLocker does not support shared locking on Win9x", RuntimeWarning)
83 # LockFile only supports immediate-fail locking.
84 if flags & LOCK_NB:
85 win32file.LockFile(hfile, 0, 0, 0xffff0000, 0)
86 else:
87 # Emulate a blocking lock with a polling loop.
88 import time
89 while 1:
90 # Attempt a lock.
91 try:
92 win32file.LockFile(hfile, 0, 0, 0xffff0000, 0)
93 break
94 except win32file.error, e:
95 # Propagate upwards all exceptions other than lock violation.
96 if e[0] != winerror.ERROR_LOCK_VIOLATION:
97 raise e
98 # Sleep and poll again.
99 time.sleep(0.1)
100 # TODO: should this return the result of the lock?
102 def unlock(file):
103 hfile = win32file._get_osfhandle(file.fileno())
104 # UnlockFileEx is not supported on all Win32 platforms (Win95, Win98, WinME).
105 # If it's not supported, win32file will raise an api_error exception.
106 try:
107 win32file.UnlockFileEx(hfile, 0, 0xffff0000, __overlapped)
108 except win32file.error, e:
109 import winerror
110 # Propagate upwards all exceptions other than not-implemented.
111 if e[0] != winerror.ERROR_CALL_NOT_IMPLEMENTED:
112 raise e
114 # UnlockFileEx is not supported. Use UnlockFile.
115 # Care: the low/high length params are reversed compared to UnLockFileEx.
116 win32file.UnlockFile(hfile, 0, 0, 0xffff0000, 0)
118 elif os.name =='posix':
119 def lock(file, flags):
120 fcntl.flock(file.fileno(), flags)
121 # TODO: should this return the result of the lock?
123 def unlock(file):
124 fcntl.flock(file.fileno(), fcntl.LOCK_UN)
126 if __name__ == '__main__':
127 from time import time, strftime, localtime
128 import sys
129 import portalocker
131 log = open('log.txt', "a+")
132 portalocker.lock(log, portalocker.LOCK_EX)
134 timestamp = strftime("%m/%d/%Y %H:%M:%S\n", localtime(time()))
135 log.write( timestamp )
137 print "Wrote lines. Hit enter to release lock."
138 dummy = sys.stdin.readline()
140 log.close()