index.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. :mod:`lockfile` --- Platform-independent file locking
  2. =====================================================
  3. .. module:: lockfile
  4. :synopsis: Platform-independent file locking
  5. .. moduleauthor:: Skip Montanaro <skip@pobox.com>
  6. .. sectionauthor:: Skip Montanaro <skip@pobox.com>
  7. .. warning::
  8. This package is **deprecated**. It is highly preferred that instead of
  9. using this code base that instead `fasteners`_ or `oslo.concurrency`_ is
  10. used instead. For any questions or comments or further help needed
  11. please email `openstack-dev`_ and prefix your email subject
  12. with ``[oslo][pylockfile]`` (for a faster response).
  13. .. note::
  14. This package is pre-release software. Between versions 0.8 and 0.9 it
  15. was changed from a module to a package. It is quite possible that the
  16. API and implementation will change again in important ways as people test
  17. it and provide feedback and bug fixes. In particular, if the mkdir-based
  18. locking scheme is sufficient for both Windows and Unix platforms, the
  19. link-based scheme may be deleted so that only a single locking scheme is
  20. used, providing cross-platform lockfile cooperation.
  21. .. note::
  22. The implementation uses the `with` statement, both in the tests and in the
  23. main code, so will only work out-of-the-box with Python 2.5 or later.
  24. However, the use of the `with` statement is minimal, so if you apply the
  25. patch in the included 2.4.diff file you can use it with Python 2.4. It's
  26. possible that it will work in Python 2.3 with that patch applied as well,
  27. though the doctest code relies on APIs new in 2.4, so will have to be
  28. rewritten somewhat to allow testing on 2.3. As they say, patches welcome.
  29. ``;-)``
  30. The :mod:`lockfile` package exports a :class:`LockFile` class which provides
  31. a simple API for locking files. Unlike the Windows :func:`msvcrt.locking`
  32. function, the Unix :func:`fcntl.flock`, :func:`fcntl.lockf` and the
  33. deprecated :mod:`posixfile` module, the API is identical across both Unix
  34. (including Linux and Mac) and Windows platforms. The lock mechanism relies
  35. on the atomic nature of the :func:`link` (on Unix) and :func:`mkdir` (On
  36. Windows) system calls. It also contains several lock-method-specific
  37. modules: :mod:`lockfile.linklockfile`, :mod:`lockfile.mkdirlockfile`, and
  38. :mod:`lockfile.sqlitelockfile`, each one exporting a single class. For
  39. backwards compatibility with versions before 0.9 the :class:`LinkFileLock`,
  40. :class:`MkdirFileLock` and :class:`SQLiteFileLock` objects are exposed as
  41. attributes of the top-level lockfile package, though this use was deprecated
  42. starting with version 0.9 and will be removed in version 1.0.
  43. .. note::
  44. The current implementation uses :func:`os.link` on Unix, but since that
  45. function is unavailable on Windows it uses :func:`os.mkdir` there. At
  46. this point it's not clear that using the :func:`os.mkdir` method would be
  47. insufficient on Unix systems. If it proves to be adequate on Unix then
  48. the implementation could be simplified and truly cross-platform locking
  49. would be possible.
  50. .. note::
  51. The current implementation doesn't provide for shared vs. exclusive
  52. locks. It should be possible for multiple reader processes to hold the
  53. lock at the same time.
  54. The module defines the following exceptions:
  55. .. exception:: Error
  56. This is the base class for all exceptions raised by the :class:`LockFile`
  57. class.
  58. .. exception:: LockError
  59. This is the base class for all exceptions raised when attempting to lock
  60. a file.
  61. .. exception:: UnlockError
  62. This is the base class for all exceptions raised when attempting to
  63. unlock a file.
  64. .. exception:: LockTimeout
  65. This exception is raised if the :func:`LockFile.acquire` method is
  66. called with a timeout which expires before an existing lock is released.
  67. .. exception:: AlreadyLocked
  68. This exception is raised if the :func:`LockFile.acquire` detects a
  69. file is already locked when in non-blocking mode.
  70. .. exception:: LockFailed
  71. This exception is raised if the :func:`LockFile.acquire` detects some
  72. other condition (such as a non-writable directory) which prevents it from
  73. creating its lock file.
  74. .. exception:: NotLocked
  75. This exception is raised if the file is not locked when
  76. :func:`LockFile.release` is called.
  77. .. exception:: NotMyLock
  78. This exception is raised if the file is locked by another thread or
  79. process when :func:`LockFile.release` is called.
  80. The following classes are provided:
  81. .. class:: linklockfile.LinkLockFile(path, threaded=True)
  82. This class uses the :func:`link(2)` system call as the basic lock
  83. mechanism. *path* is an object in the file system to be locked. It need
  84. not exist, but its directory must exist and be writable at the time the
  85. :func:`acquire` and :func:`release` methods are called. *threaded* is
  86. optional, but when set to :const:`True` locks will be distinguished
  87. between threads in the same process.
  88. .. class:: symlinklockfile.SymlinkLockFile(path, threaded=True)
  89. This class uses the :func:`symlink(2)` system call as the basic lock
  90. mechanism. The parameters have the same meaning and constraints as for
  91. the :class:`LinkLockFile` class.
  92. .. class:: mkdirlockfile.MkdirLockFile(path, threaded=True)
  93. This class uses the :func:`mkdir(2)` system call as the basic lock
  94. mechanism. The parameters have the same meaning and constraints as for
  95. the :class:`LinkLockFile` class.
  96. .. class:: sqlitelockfile.SQLiteLockFile(path, threaded=True)
  97. This class uses the :mod:`sqlite3` module to implement the lock
  98. mechanism. The parameters have the same meaning as for the
  99. :class:`LinkLockFile` class.
  100. .. class:: LockBase(path, threaded=True)
  101. This is the base class for all concrete implementations and is available
  102. at the lockfile package level so programmers can implement other locking
  103. schemes.
  104. .. function:: locked(path, timeout=None)
  105. This function provides a decorator which insures the decorated function
  106. is always called with the lock held.
  107. By default, the :const:`LockFile` object refers to the
  108. :class:`mkdirlockfile.MkdirLockFile` class on Windows. On all other
  109. platforms it refers to the :class:`linklockfile.LinkLockFile` class.
  110. When locking a file the :class:`linklockfile.LinkLockFile` class creates a
  111. uniquely named hard link to an empty lock file. That hard link contains the
  112. hostname, process id, and if locks between threads are distinguished, the
  113. thread identifier. For example, if you want to lock access to a file named
  114. "README", the lock file is named "README.lock". With per-thread locks
  115. enabled the hard link is named HOSTNAME-THREADID-PID. With only per-process
  116. locks enabled the hard link is named HOSTNAME--PID.
  117. When using the :class:`mkdirlockfile.MkdirLockFile` class the lock file is a
  118. directory. Referring to the example above, README.lock will be a directory
  119. and HOSTNAME-THREADID-PID will be an empty file within that directory.
  120. .. seealso::
  121. Module :mod:`msvcrt`
  122. Provides the :func:`locking` function, the standard Windows way of
  123. locking (parts of) a file.
  124. Module :mod:`posixfile`
  125. The deprecated (since Python 1.5) way of locking files on Posix systems.
  126. Module :mod:`fcntl`
  127. Provides the current best way to lock files on Unix systems
  128. (:func:`lockf` and :func:`flock`).
  129. LockFile Objects
  130. ----------------
  131. :class:`LockFile` objects support the `context manager` protocol used by the
  132. statement:`with` statement. The timeout option is not supported when used in
  133. this fashion. While support for timeouts could be implemented, there is no
  134. support for handling the eventual :exc:`Timeout` exceptions raised by the
  135. :func:`__enter__` method, so you would have to protect the `with` statement with
  136. a `try` statement. The resulting construct would not be any simpler than just
  137. using a `try` statement in the first place.
  138. :class:`LockFile` has the following user-visible methods:
  139. .. method:: LockFile.acquire(timeout=None)
  140. Lock the file associated with the :class:`LockFile` object. If the
  141. *timeout* is omitted or :const:`None` the caller will block until the
  142. file is unlocked by the object currently holding the lock. If the
  143. *timeout* is zero or a negative number the :exc:`AlreadyLocked` exception
  144. will be raised if the file is currently locked by another process or
  145. thread. If the *timeout* is positive, the caller will block for that
  146. many seconds waiting for the lock to be released. If the lock is not
  147. released within that period the :exc:`LockTimeout` exception will be
  148. raised.
  149. .. method:: LockFile.release()
  150. Unlock the file associated with the :class:`LockFile` object. If the
  151. file is not currently locked, the :exc:`NotLocked` exception is raised.
  152. If the file is locked by another thread or process the :exc:`NotMyLock`
  153. exception is raised.
  154. .. method:: is_locked()
  155. Return the status of the lock on the current file. If any process or
  156. thread (including the current one) is locking the file, :const:`True` is
  157. returned, otherwise :const:`False` is returned.
  158. .. method:: break_lock()
  159. If the file is currently locked, break it.
  160. .. method:: i_am_locking()
  161. Returns true if the caller holds the lock.
  162. Examples
  163. --------
  164. This example is the "hello world" for the :mod:`lockfile` package::
  165. from lockfile import LockFile
  166. lock = LockFile("/some/file/or/other")
  167. with lock:
  168. print lock.path, 'is locked.'
  169. To use this with Python 2.4, you can execute::
  170. from lockfile import LockFile
  171. lock = LockFile("/some/file/or/other")
  172. lock.acquire()
  173. print lock.path, 'is locked.'
  174. lock.release()
  175. If you don't want to wait forever, you might try::
  176. from lockfile import LockFile
  177. lock = LockFile("/some/file/or/other")
  178. while not lock.i_am_locking():
  179. try:
  180. lock.acquire(timeout=60) # wait up to 60 seconds
  181. except LockTimeout:
  182. lock.break_lock()
  183. lock.acquire()
  184. print "I locked", lock.path
  185. lock.release()
  186. You can also insure that a lock is always held when appropriately decorated
  187. functions are called::
  188. from lockfile import locked
  189. @locked("/tmp/mylock")
  190. def func(a, b):
  191. return a + b
  192. Other Libraries
  193. ---------------
  194. The idea of implementing advisory locking with a standard API is not new
  195. with :mod:`lockfile`. There are a number of other libraries available:
  196. * locknix - http://pypi.python.org/pypi/locknix - Unix only
  197. * mx.MiscLockFile - from Marc André Lemburg, part of the mx.Base
  198. distribution - cross-platform.
  199. * Twisted - http://twistedmatrix.com/trac/browser/trunk/twisted/python/lockfile.py
  200. * zc.lockfile - http://pypi.python.org/pypi/zc.lockfile
  201. Contacting the Author
  202. ---------------------
  203. If you encounter any problems with ``lockfile``, would like help or want to
  204. submit a patch, check http://launchpad.net/pylockfile
  205. .. _fasteners: http://fasteners.readthedocs.org/
  206. .. _openstack-dev: mailto:openstack-dev@lists.openstack.org
  207. .. _oslo.concurrency: http://docs.openstack.org/developer/oslo.concurrency/