Skip to content

Latest commit

 

History

History
151 lines (100 loc) · 4.48 KB

index.rst

File metadata and controls

151 lines (100 loc) · 4.48 KB

filelock

This package contains a single module, which implements a platform independent file lock in Python, which provides a simple way of inter-process communication:

from filelock import Timeout, FileLock

lock = FileLock("high_ground.txt.lock")
with lock:
    open("high_ground.txt", "a").write("You were the chosen one.")

Don't use a FileLock <filelock.FileLock> to lock the file you want to write to, instead create a separate .lock file as shown above.

Example gif

Similar libraries

Perhaps you are looking for something like:

  • the pid 3rd party library,
  • for Windows the msvcrt module in the standard library,
  • for UNIX the fcntl module in the standard library.

Installation

filelock is available via PyPI, so you can pip install it:

python -m pip install filelock

Tutorial

A FileLock <filelock.FileLock> is used to indicate another process of your application that a resource or working directory is currently used. To do so, create a FileLock <filelock.FileLock> first:

from filelock import Timeout, FileLock

file_path = "high_ground.txt"
lock_path = "high_ground.txt.lock"

lock = FileLock(lock_path, timeout=1)

The lock object supports multiple ways for acquiring the lock, including the ones used to acquire standard Python thread locks:

with lock:
    open(file_path, "a").write("Hello there!")

lock.acquire()
try:
    open(file_path, "a").write("General Kenobi!")
finally:
    lock.release()


@lock
def decorated():
    print("You're a decorated Jedi!")


decorated()

The acquire <filelock.BaseFileLock.acquire> method accepts also a timeout parameter. If the lock cannot be acquired within timeout seconds, a Timeout <filelock.Timeout> exception is raised:

try:
    with lock.acquire(timeout=10):
        open(file_path, "a").write("I have a bad feeling about this.")
except Timeout:
    print("Another instance of this application currently holds the lock.")

The lock objects are recursive locks, which means that once acquired, they will not block on successive lock requests:

def cite1():
    with lock:
        open(file_path, "a").write("I hate it when he does that.")


def cite2():
    with lock:
        open(file_path, "a").write("You don't want to sell me death sticks.")


# The lock is acquired here.
with lock:
    cite1()
    cite2()
# And released here.

Logging

All log messages by this library are made using the DEBUG_ level, under the filelock name. On how to control displaying/hiding that please consult the logging documentation of the standard library. E.g. to hide these messages you can use:

logging.getLogger("filelock").setLevel(logging.INFO)

FileLock vs SoftFileLock

The FileLock <filelock.FileLock> is platform dependent while the SoftFileLock <filelock.SoftFileLock> is not. Use the FileLock <filelock.FileLock> if all instances of your application are running on the same platform and a SoftFileLock <filelock.SoftFileLock> otherwise.

The SoftFileLock <filelock.SoftFileLock> only watches the existence of the lock file. This makes it ultra portable, but also more prone to dead locks if the application crashes. You can simply delete the lock file in such cases.

Asyncio support

This library currently does not support asyncio. We'd recommend adding an asyncio variant though if someone can make a pull request for it, see here.

Contributions and issues

Contributions are always welcome, please make sure they pass all tests before creating a pull request. This module is hosted on GitHub. If you have any questions or suggestions, don't hesitate to open a new issue 😊. There's no bad question, just a missed opportunity to learn more.

self api license changelog