|
2 | 2 | # Requires python 1.5.2 or better. |
3 | 3 |
|
4 | 4 | # ID line added by richard for Roundup file tracking |
5 | | -# $Id: portalocker.py,v 1.2 2002-10-03 06:56:29 richard Exp $ |
| 5 | +# $Id: portalocker.py,v 1.3 2003-01-19 23:14:42 richard Exp $ |
6 | 6 |
|
7 | 7 | """ Cross-platform (posix/nt) API for flock-style file locking. |
8 | 8 |
|
|
43 | 43 | import os |
44 | 44 |
|
45 | 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() |
| 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 | 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 |
| 55 | + import fcntl |
| 56 | + LOCK_EX = fcntl.LOCK_EX |
| 57 | + LOCK_SH = fcntl.LOCK_SH |
| 58 | + LOCK_NB = fcntl.LOCK_NB |
59 | 59 | else: |
60 | | - raise RuntimeError("PortaLocker only defined for nt and posix platforms") |
| 60 | + raise RuntimeError("PortaLocker only defined for nt and posix platforms") |
61 | 61 |
|
62 | 62 | if os.name == 'nt': |
63 | | - def lock(file, flags): |
64 | | - hfile = win32file._get_osfhandle(file.fileno()) |
65 | | - win32file.LockFileEx(hfile, flags, 0, 0xffff0000, __overlapped) |
66 | | - |
67 | | - def unlock(file): |
68 | | - hfile = win32file._get_osfhandle(file.fileno()) |
69 | | - win32file.UnlockFileEx(hfile, 0, 0xffff0000, __overlapped) |
| 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 |
| 76 | + |
| 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? |
| 101 | + |
| 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 |
| 113 | + |
| 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) |
70 | 117 |
|
71 | 118 | elif os.name =='posix': |
72 | | - def lock(file, flags): |
73 | | - fcntl.flock(file.fileno(), flags) |
| 119 | + def lock(file, flags): |
| 120 | + fcntl.flock(file.fileno(), flags) |
| 121 | + # TODO: should this return the result of the lock? |
74 | 122 |
|
75 | | - def unlock(file): |
76 | | - fcntl.flock(file.fileno(), fcntl.LOCK_UN) |
| 123 | + def unlock(file): |
| 124 | + fcntl.flock(file.fileno(), fcntl.LOCK_UN) |
77 | 125 |
|
78 | 126 | if __name__ == '__main__': |
79 | | - from time import time, strftime, localtime |
80 | | - import sys |
81 | | - import portalocker |
| 127 | + from time import time, strftime, localtime |
| 128 | + import sys |
| 129 | + import portalocker |
82 | 130 |
|
83 | | - log = open('log.txt', "a+") |
84 | | - portalocker.lock(log, portalocker.LOCK_EX) |
| 131 | + log = open('log.txt', "a+") |
| 132 | + portalocker.lock(log, portalocker.LOCK_EX) |
85 | 133 |
|
86 | | - timestamp = strftime("%m/%d/%Y %H:%M:%S\n", localtime(time())) |
87 | | - log.write( timestamp ) |
| 134 | + timestamp = strftime("%m/%d/%Y %H:%M:%S\n", localtime(time())) |
| 135 | + log.write( timestamp ) |
88 | 136 |
|
89 | | - print "Wrote lines. Hit enter to release lock." |
90 | | - dummy = sys.stdin.readline() |
| 137 | + print "Wrote lines. Hit enter to release lock." |
| 138 | + dummy = sys.stdin.readline() |
91 | 139 |
|
92 | | - log.close() |
| 140 | + log.close() |
93 | 141 |
|
0 commit comments