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.
Python code
23 linesimport 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
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
- Use a blocking lock by omitting `LOCK_NB` to wait until the lock is available.
- 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
More from Files & data
- Append a Line to a Log File in Python easy
- Audit File Permissions Across a Project in Python easy
- Automatically Detect Corrupted Files Using SHA-256 Checksums in Python easy
- Automatically Highlight Data Validation Errors Inside Excel Files in Python easy
- Build a Command-Line To-Do List Application with Data Persistence in Python easy
- Build a File Index by Relative Path Hash Map in Python easy
Keep learning
Related tutorials and quizzes for this topic.