Mercurial > hg > cc > cirrus_home
comparison lib/python/lock.py @ 87:b6a5999d8e06
working with locking and copying
author | Henry S. Thompson <ht@inf.ed.ac.uk> |
---|---|
date | Tue, 16 Mar 2021 16:20:02 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
86:b5fef78cbb26 | 87:b6a5999d8e06 |
---|---|
1 # Courtesy of https://stackoverflow.com/a/46407326 | |
2 import fcntl, os | |
3 def lock_file(f): | |
4 if f.writable(): fcntl.lockf(f, fcntl.LOCK_EX) | |
5 def unlock_file(f): | |
6 if f.writable(): fcntl.lockf(f, fcntl.LOCK_UN) | |
7 | |
8 # Class for ensuring that all file operations are atomic, treat | |
9 # initialization like a standard call to 'open' that happens to be atomic. | |
10 # This file opener *must* be used in a "with" block. | |
11 class AtomicOpen: | |
12 # Open the file with arguments provided by user. Then acquire | |
13 # a lock on that file object (WARNING: Advisory locking). | |
14 def __init__(self, path, *args, **kwargs): | |
15 # Open the file and acquire a lock on the file before operating | |
16 self.file = open(path,*args, **kwargs) | |
17 # Lock the opened file | |
18 lock_file(self.file) | |
19 | |
20 # Return the opened file object (knowing a lock has been obtained). | |
21 def __enter__(self, *args, **kwargs): return self.file | |
22 | |
23 # Unlock the file and close the file object. | |
24 def __exit__(self, exc_type=None, exc_value=None, traceback=None): | |
25 # Flush to make sure all buffered contents are written to file. | |
26 self.file.flush() | |
27 os.fsync(self.file.fileno()) | |
28 # Release the lock on the file. | |
29 unlock_file(self.file) | |
30 self.file.close() | |
31 # Handle exceptions that may have come up during execution, by | |
32 # default any exceptions are raised to the user. | |
33 if (exc_type != None): return False | |
34 else: return True |