Portalocker is a Python library that provides an easy-to-use API for cross-platform file locking. It supports file locking on Windows, Linux, BSD, and Unix systems, and can also facilitate distributed locking using Redis. The library is actively maintained, follows Semantic Versioning, and provides a convenient context manager for lock management.
Install & Compatibility
Where this runs
tested against v3.2.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.950 runs
installs and imports cleanly · install 0.0s · import 0.302s · 22.7MB
glibcpy 3.10–3.950 runs
installs and imports cleanly · install 1.8s · import 0.285s · 23MB
21MB installed
● package 21MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
lock
✓ from portalocker import lock
For low-level, manual locking. The context manager `Lock` is generally preferred.
unlock
✓ from portalocker import unlock
For low-level, manual unlocking. The context manager `Lock` handles unlocking automatically.
Lock
✓ from portalocker import Lock
RLock
✓ from portalocker import RLock
Reentrant lock, similar to `threading.RLock` but for processes.
BoundedSemaphore
✓ from portalocker import BoundedSemaphore
RedisLock
✓ from portalocker import RedisLock
Requires `portalocker[redis]` extra to be installed.
LockFlags
✓ from portalocker import LockFlags
AlreadyLocked
✓ from portalocker.exceptions import AlreadyLocked
This quickstart demonstrates the recommended way to use `portalocker` with the `Lock` context manager to safely acquire and release file locks, ensuring data integrity across processes. It explicitly shows flushing and syncing the file content to disk.
import portalocker
import os
file_path = 'my_locked_file.txt'
# Using the Lock context manager (recommended)
# The file is created/opened with 'a' mode, preventing truncation before lock
with portalocker.Lock(file_path, timeout=5, mode='a', truncate=0) as fh:
print(f"Acquired lock on {file_path}. PID: {os.getpid()}")
fh.write(f"Hello from process {os.getpid()}!\n")
fh.flush()
os.fsync(fh.fileno())
print("Wrote data and flushed.")
# Lock is automatically released when exiting the 'with' block
print(f"Released lock on {file_path}.")
# Example of manual locking (less common, use with care)
# try:
# f = open(file_path, 'r+')
# portalocker.lock(f, portalocker.LockFlags.EXCLUSIVE)
# print(f"Manually acquired lock on {file_path}")
# f.seek(0)
# f.write(f"Manual write from process {os.getpid()}\n")
# f.flush()
# os.fsync(f.fileno())
# finally:
# portalocker.unlock(f)
# f.close()
# print(f"Manually released lock on {file_path}")
Errors
Common errors & fixes
portalocker.exceptions.LockException: [Errno 11] Resource temporarily unavailable
This error occurs when a process attempts to acquire a file lock, but the file is already locked by another process, and the acquisition attempt is non-blocking or times out before the lock can be obtained.
fixTo resolve this, you can either implement a retry mechanism for acquiring the lock with a suitable timeout, or configure `portalocker.Lock` to wait by setting an appropriate `timeout` parameter (which defaults to `None` for infinite wait, but can be set to a float for a specific duration). If `fail_when_locked=True` (the default for `Lock`), you might catch `portalocker.exceptions.AlreadyLocked` for immediate failure, or set `fail_when_locked=False` to make it block until timeout.
redis.exceptions.ConnectionError: Error 10061 connecting to localhost:6379. No connection could be made because the target machine actively refused it.
This error specifically occurs when using `portalocker.RedisLock` and the Python application is unable to establish a connection to the Redis server. This is commonly due to the Redis server not running, being configured to listen on a different host/port, or being blocked by a firewall.
fixVerify that your Redis server is running and accessible from the machine where your Python application is executing. Ensure that the host and port specified when initializing `portalocker.RedisLock` (or the underlying Redis connection) correctly match your Redis server's configuration. For example: `import portalocker; import redis; client = redis.Redis(host='your_redis_host', port=6379); lock = portalocker.RedisLock('my_channel', connection=client)`. PermissionError: [Errno 13] Permission denied
This operating system error indicates that the Python process does not have the necessary permissions (read, write, or execute) to access, create, or modify the lock file or the directory where the lock file is being created.
fixGrant the user running the Python script the appropriate read and write permissions for the directory where `portalocker` attempts to create its lock files, and for the file being locked itself. This often involves using `chmod` and `chown` commands on Unix-like systems or adjusting security settings on Windows.
ImportError: cannot import name 'portalocker'
This error typically means the `portalocker` package is not installed in the active Python environment, or there is an issue with the Python environment path. Less commonly, a `SyntaxError` during import can occur if a version of `portalocker` that uses Python 3+ specific syntax (like type hints) is run with an older Python interpreter (e.g., Python 3.5 or earlier).
fixFirst, ensure `portalocker` is correctly installed in your current Python environment using `pip install portalocker`. If you are working with older Python versions, consider upgrading your Python interpreter to 3.7+ or installing a compatible older version of `portalocker` (e.g., `pip install 'portalocker<2'` for Python 2.x environments if absolutely necessary). Verify that your Python interpreter is pointing to the correct environment where the package is installed.
ModuleNotFoundError: No module named 'portalocker'
The 'portalocker' Python package has not been installed in your current environment.
fixpip install portalocker
Audit
Dependencies
redisoptionalRequired for using Redis-based distributed locks (`portalocker.RedisLock`).