A file locking mechanism that has context-manager support so you can use it in a with statement. This should be relatively cross compatible as it doesn't rely on msvcrt or fcntl for the locking.
| 220 | pass |
| 221 | |
| 222 | class FileLock(object): |
| 223 | """ A file locking mechanism that has context-manager support so |
| 224 | you can use it in a with statement. This should be relatively cross |
| 225 | compatible as it doesn't rely on msvcrt or fcntl for the locking. |
| 226 | """ |
| 227 | |
| 228 | def __init__(self, file_name, timeout=10, delay=.05): |
| 229 | """ Prepare the file locker. Specify the file to lock and optionally |
| 230 | the maximum timeout and the delay between each attempt to lock. |
| 231 | """ |
| 232 | self.is_locked = False |
| 233 | self.lockfile = os.path.join(os.getcwd(), "%s.lock" % file_name) |
| 234 | self.file_name = file_name |
| 235 | self.timeout = timeout |
| 236 | self.delay = delay |
| 237 | |
| 238 | def acquire(self): |
| 239 | """ Acquire the lock, if possible. If the lock is in use, it check again |
| 240 | every `wait` seconds. It does this until it either gets the lock or |
| 241 | exceeds `timeout` number of seconds, in which case it throws |
| 242 | an exception. |
| 243 | """ |
| 244 | if self.is_locked: |
| 245 | return |
| 246 | |
| 247 | start_time = time.time() |
| 248 | while True: |
| 249 | try: |
| 250 | self.fd = os.open(self.lockfile, os.O_CREAT|os.O_EXCL|os.O_RDWR) |
| 251 | break; |
| 252 | except OSError as e: |
| 253 | if e.errno != errno.EEXIST: |
| 254 | raise |
| 255 | |
| 256 | if (time.time() - start_time) >= self.timeout: |
| 257 | raise FileLockException("Timeout occured.") |
| 258 | time.sleep(self.delay) |
| 259 | self.is_locked = True |
| 260 | |
| 261 | def release(self): |
| 262 | """ Get rid of the lock by deleting the lockfile. |
| 263 | When working in a `with` statement, this gets automatically |
| 264 | called at the end. |
| 265 | """ |
| 266 | if self.is_locked: |
| 267 | os.close(self.fd) |
| 268 | os.unlink(self.lockfile) |
| 269 | self.is_locked = False |
| 270 | |
| 271 | def __enter__(self): |
| 272 | """ Activated when used in the with statement. |
| 273 | Should automatically acquire a lock to be used in the with block. |
| 274 | """ |
| 275 | if not self.is_locked: |
| 276 | self.acquire() |
| 277 | return self |
| 278 | |
| 279 | def __exit__(self, type, value, traceback): |