How to Use fcntl for Exclusive File Locking in Python

This code demonstrates how to acquire an exclusive advisory lock on a file using fcntl.flock with a non-blocking flag, simulate work, then release the lock.

Medium Python 3.9+ Aug 9, 2026 Files & data 12 views 0 copies

Python code

23 lines
Python 3.9+
import fcntl
import os
import tempfile
import time

def acquire_exclusive_lock(filepath):
    fd = os.open(filepath, os.O_RDWR | os.O_CREAT)
    try:
        fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
        print(f"Exclusive lock acquired on {filepath}")
        time.sleep(1)  # Simulate work while holding the lock
    except BlockingIOError:
        print(f"Could not acquire lock on {filepath} — held by another process")
    finally:
        fcntl.flock(fd, fcntl.LOCK_UN)
        os.close(fd)

if __name__ == "__main__":
    with tempfile.NamedTemporaryFile(delete=False) as tmp:
        tmp_path = tmp.name
    acquire_exclusive_lock(tmp_path)
    acquire_exclusive_lock(tmp_path)  # Second attempt should succeed after release
    os.unlink(tmp_path)

Output

stdout
Exclusive lock acquired on /tmp/tmpabc123
Exclusive lock acquired on /tmp/tmpabc123

How it works

The os.open call creates the file if it does not exist and opens it for read/write, providing the file descriptor needed by fcntl.flock. fcntl.LOCK_EX requests an exclusive lock, while LOCK_NB makes the call non-blocking; if the lock is held elsewhere, BlockingIOError is raised immediately. The finally block ensures the lock is released and the file descriptor is closed, even if an exception occurs. Because the lock is released before the second call, the second attempt succeeds, confirming the lock is no longer held. Note that flock locks are advisory: other processes must cooperate by using the same locking mechanism.

Common mistakes

  • Forgetting to close the file descriptor, leaving the lock held until the process exits.
  • Using `LOCK_NB` without handling `BlockingIOError`, causing the program to crash.
  • Assuming flock works on Windows; it is Unix-only (use `msvcrt` on Windows).
  • Not releasing the lock in a `finally` block, risking a deadlock on error.

Variations

  1. Use a blocking lock by omitting `LOCK_NB` to wait until the lock is available.
  2. Use `fcntl.lockf` or `os.lockf` for a POSIX record-locking alternative.

Real-world use cases

  • Preventing multiple cron jobs from writing to the same log or data file concurrently.
  • Serializing access to a shared resource like a SQLite database or a state file across processes.
  • Ensuring only one instance of a long-running daemon starts at a time (singleton pattern).

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Files & data

Related tutorials and quizzes for this topic.