1 """!Handles file locking using Python "with" blocks.
3 This module implements a Python with construct that can hold a lock
4 and release it at the end of the "with" block. It also implements a
5 safety feature to allow the program to disable locking, ensuring a
6 fatal exception (LockingDisabled) if anything tries to lock a file.
7 That functionality is connected to the produtil.sigsafety module,
8 which will disable locking if a fatal signal is received.
11 import produtil.locking
12 with produtil.locking.LockFile("some.lockfile"):
13 ... do things while the file is locked...
14 ... the file is now unlocked ...
17 import fcntl, time, errno, os.path
23 __all__=[
'LockingDisabled',
'disable_locking',
'LockFile',
'LockHeld']
37 """!Entirely disables all locking in this module.
39 If this is called, any locking attempts will raise
40 LockingDisabled. That exception derives directly from
41 BaseException, which well-written Python code will never catch,
42 hence ensuring a rapid, abnormal exit of the program. This
43 routine should never be called directly: it is only used as part
44 of the implementation of the produtil.sigsafety, to prevent file
45 locking after catching a terminal signal, hence allowing the
46 program to exit as quickly as possible, and present a stack trace
47 to any locations that attempt locking."""
53 except (Exception,LockingDisabled)
as l:
pass
56 """!This exception is raised when a LockFile cannot lock a file
57 because another process or thread has locked it already."""
59 class LockingDisabled(BaseException):
60 """!This exception is raised when a thread attempts to acquire a
61 lock while Python is exiting according to produtil.sigsafety.
63 @warning This is a subclass of BaseException, not Exception, to
64 attempt to cleanly kill the thread."""
67 """!Automates locking of a lockfile
70 with LockFile("/path/to/lock.file"):
71 ... do things while file is locked ...
72 ...file is no longer locked.
75 """!Return a hash of this object."""
78 """!Is this lock the same as that lock?"""
80 def __init__(self,filename,until=None,logger=None,max_tries=10,sleep_time=3,first_warn=0,giveup_quiet=False):
81 """!Creates an object that will lock the specified file.
82 @param filename the file to lock
84 @param logger Optional: a logging.Logger to log messages
85 @param max_tries Optional: maximum tries before giving up on locking
86 @param sleep_time Optional: approximate sleep time between
88 @param first_warn Optional: first locking failure at which to
89 write warnings to the logger
90 @param giveup_quiet Optional: if True, do not log the final
93 raise LockingDisabled(
'Attempted to create a LockFile object while the process was exiting.')
95 assert(filename
is not None)
96 assert(len(filename)>0)
104 """!Internal implementation function; do not call directly.
105 Does the actual work of acquiring the lock, without retries,
106 logging or sleeping. Will raise LockHeld if it cannot acquire
110 'the process was exiting.')
117 fcntl.lockf(self._fd.fileno(),fcntl.LOCK_EX|fcntl.LOCK_NB)
118 except EnvironmentError
as e:
119 if e.errno == errno.EAGAIN
or e.errno == errno.EWOULDBLOCK:
120 raise LockHeld(
'%s: already locked by another process or '
124 """!Internal implementation function; do not call directly.
125 Does the actual work of releasing the lock, without retries,
126 logging or sleeping."""
127 if self.
_fd is not None:
128 fcntl.lockf(self._fd.fileno(),fcntl.LOCK_UN)
132 """!Acquire the lock. Will try for a while, and will raise
133 LockHeld when giving up."""
139 """!Release the lock. May raise exceptions on unexpected
150 """!Calls self.acquire() to acquire the lock."""
154 """!Calls self.release() to release the lock.
155 @param etype,evalue,etraceback Exception information."""
This module provides a set of utility functions to do filesystem operations.
This exception is raised when a LockFile cannot lock a file because another process or thread has loc...
def disable_locking()
Entirely disables all locking in this module.
def __enter__(self)
Calls self.acquire() to acquire the lock.
def release(self)
Release the lock.
def __exit__(self, etype, evalue, etraceback)
Calls self.release() to release the lock.
def __hash__(self)
Return a hash of this object.
def acquire_impl(self)
Internal implementation function; do not call directly.
Contains retry_io() which automates retrying operations.
def __init__
Creates an object that will lock the specified file.
def release_impl(self)
Internal implementation function; do not call directly.
def makedirs
Make a directory tree, working around filesystem bugs.
def __eq__(self, other)
Is this lock the same as that lock?
This exception is raised when a thread attempts to acquire a lock while Python is exiting according t...
Automates locking of a lockfile.
def acquire(self)
Acquire the lock.