API Reference

This section documents all public classes, exceptions, and attributes. For usage examples and task-oriented guidance, see Tutorials and How-to guides.

FileLock and AsyncFileLock are platform aliases: at import time they resolve to UnixFileLock or WindowsFileLock (and their async peers), or to the soft backends on a build without fcntl. The shared acquire / release / timeout interface they expose lives on BaseFileLock and BaseAsyncFileLock below.

A platform independent file lock that supports the with-statement.

filelock.__version__

version of the project as a string

class filelock.AcquireReturnProxy(lock)[source]

Bases: object

A context-aware object that will release the lock file when exiting.

class filelock.AsyncAcquireReadWriteReturnProxy(lock)[source]

Bases: object

Context-aware object that releases the async read/write lock on exit.

class filelock.AsyncAcquireReturnProxy(lock)[source]

Bases: object

A context-aware object that will release the lock file when exiting.

class filelock.AsyncAcquireSoftReadWriteReturnProxy(lock)[source]

Bases: object

Async context-aware object that releases an AsyncSoftReadWriteLock on exit.

filelock.AsyncFileLock

alias of AsyncUnixFileLock

class filelock.AsyncReadWriteLock(lock_file, timeout=-1, *, blocking=True, is_singleton=True, loop=None, executor=None)[source]

Bases: object

Async wrapper around ReadWriteLock for use in asyncio applications.

This wrapper dispatches every blocking SQLite operation to a thread pool via loop.run_in_executor() because Python’s sqlite3 module has no async API. It delegates reentrancy, upgrade/downgrade rules, and singleton behavior to the underlying ReadWriteLock.

Parameters:
  • lock_file (str | PathLike[str]) – path to the SQLite database file used as the lock

  • timeout (float) – maximum wait time in seconds; -1 means block indefinitely

  • blocking (bool) – if False, raise Timeout immediately when the lock is unavailable

  • is_singleton (bool) – if True, reuse existing ReadWriteLock instances for the same resolved path

  • loop (AbstractEventLoop | None) – event loop for run_in_executor; None uses the running loop

  • executor (Executor | None) – executor for run_in_executor. When None this lock creates and owns a dedicated single-thread executor so every operation runs on the same thread (SQLite affinity requires this) and shuts it down in close(). This lock uses a caller-supplied executor as-is and never shuts it down, so after passing no executor call close() to release the owned one.

Added in version 3.21.0.

property lock_file

The path to the lock file.

property timeout

The default timeout.

property blocking

Whether blocking is enabled by default.

property loop

The event loop (or None for the running loop).

property executor

The executor used for run_in_executor (a dedicated single-thread one if none was supplied).

read_lock(timeout=None, *, blocking=None)[source]

Async context manager that acquires and releases a shared read lock.

Falls back to instance defaults for timeout and blocking when None.

Parameters:
  • timeout (float | None) – maximum wait time in seconds, or None to use the instance default

  • blocking (bool | None) – if False, raise Timeout immediately; None uses the instance default

Return type:

AsyncGenerator[None]

write_lock(timeout=None, *, blocking=None)[source]

Async context manager that acquires and releases an exclusive write lock.

Falls back to instance defaults for timeout and blocking when None.

Parameters:
  • timeout (float | None) – maximum wait time in seconds, or None to use the instance default

  • blocking (bool | None) – if False, raise Timeout immediately; None uses the instance default

Return type:

AsyncGenerator[None]

async acquire_read(timeout=-1, *, blocking=True)[source]

Acquire a shared read lock.

See ReadWriteLock.acquire_read() for full semantics.

Parameters:
  • timeout (float) – maximum wait time in seconds; -1 means block indefinitely

  • blocking (bool) – if False, raise Timeout immediately when the lock is unavailable

Return type:

AsyncAcquireReadWriteReturnProxy

Returns:

a proxy that can be used as an async context manager to release the lock

Raises:
  • RuntimeError – if a write lock is already held on this instance

  • Timeout – if the lock cannot be acquired within timeout seconds

async acquire_write(timeout=-1, *, blocking=True)[source]

Acquire an exclusive write lock.

See ReadWriteLock.acquire_write() for full semantics.

Parameters:
  • timeout (float) – maximum wait time in seconds; -1 means block indefinitely

  • blocking (bool) – if False, raise Timeout immediately when the lock is unavailable

Return type:

AsyncAcquireReadWriteReturnProxy

Returns:

a proxy that can be used as an async context manager to release the lock

Raises:
  • RuntimeError – if a read lock is already held, or a write lock is held by a different thread

  • Timeout – if the lock cannot be acquired within timeout seconds

async release(*, force=False)[source]

Release one level of the current lock.

See ReadWriteLock.release() for full semantics.

Parameters:

force (bool) – if True, release the lock completely regardless of the current lock level

Raises:

RuntimeError – if no lock is currently held and force is False

Return type:

None

async close()[source]

Release the lock (if held) and close the underlying SQLite connection.

After calling this method, the lock instance is no longer usable.

Return type:

None

class filelock.AsyncSoftFileLease(lock_file, *, lease_duration=30.0, heartbeat_interval=None, on_compromise=None, **kwargs)[source]

Bases: SoftFileLease, BaseAsyncFileLock

Existence lock whose claim expires, so a peer may take it while the previous holder still runs.

Create a lease.

Parameters:
  • lease_duration (float) – seconds of marker staleness after which a contender may take the claim. Every contender for the path must pass the same value.

  • heartbeat_interval (float | None) – seconds between refreshes. Defaults to a third of lease_duration, leaving room for two missed refreshes before a peer may take the claim. Must be shorter than lease_duration.

  • on_compromise (Callable[[LeaseCompromise], None] | None) – called from the heartbeat thread with a LeaseCompromise when the claim is lost.

  • kwargs (Unpack[LockOptions]) – every other BaseFileLock option, timeout and mode among them. The metaclass passes them all by keyword, and taking them here lets AsyncSoftFileLease add the async plumbing a fixed signature would hide.

class filelock.AsyncSoftFileLock(lock_file, timeout=-1, mode=-1, thread_local=False, *, blocking=True, is_singleton=False, poll_interval=0.05, lifetime=None, context_error_policy='chain', close_error_policy='default', fallback_to_soft=True, preserve_lock_file=False, on_acquired=None, loop=None, run_in_executor=True, executor=None)[source]

Bases: SoftFileLock, BaseAsyncFileLock

Simply watches the existence of the lock file.

Create a new lock object.

Parameters:
  • lock_file (str | PathLike[str]) – path to the file

  • timeout (float) – default timeout when acquiring the lock, in seconds. It will be used as fallback value in the acquire method, if no timeout value (None) is given. If you want to disable the timeout, set it to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.

  • mode (int) – file permissions for the lockfile. When not specified, the OS controls permissions via umask and default ACLs, preserving POSIX default ACL inheritance in shared directories.

  • thread_local (bool) – Whether this object’s internal context should be thread local or not. If this is set to False then the lock will be reentrant across threads. When True (the default), all fields of the lock’s internal context are per-thread, including the configuration values poll_interval, timeout, blocking, mode, and lifetime. Setting one of these properties from one thread does not change the value seen by another thread; threads that did not perform the write continue to see the value supplied at construction time. mode has no setter, so construction is the only place it is ever set. If you need configuration values to be visible across threads, construct the lock with thread_local=False.

  • blocking (bool) – whether the lock should be blocking or not

  • is_singleton (bool) – If this is set to True then only one instance of this class will be created per lock file. This is useful if you want to use the lock object for reentrant locking without needing to pass the same object around.

  • poll_interval (float) – default interval for polling the lock file, in seconds. It will be used as fallback value in the acquire method, if no poll_interval value (None) is given.

  • lifetime (float | None) – for AsyncSoftFileLock, the age in seconds after which a waiting process may delete the marker, even while its holder remains alive. This legacy expiry mode does not provide strict mutual exclusion. None (the default) disables age-based expiry. Native OS locks (AsyncFileLock) cannot be revoked by file age and ignore a non-None lifetime with a warning.

  • context_error_policy (Literal['chain', 'group']) – how a context manager reconciles a failure in its body with a failure while releasing on exit. "chain" (the default) keeps Python’s behavior: the release error propagates with the body error in its __context__. "group" raises a BaseExceptionGroup holding the body error first and the release error second, so neither hides the other.

  • close_error_policy (Literal['default', 'raise', 'suppress']) – for native locks (AsyncFileLock), what to do with an os.close failure after the OS unlock has already committed. "default" keeps each platform’s historical behavior, "raise" always propagates the OSError, and "suppress" always ignores it.

  • fallback_to_soft (bool) – for AsyncFileLock, whether to fall back to soft existence locking when flock returns ENOSYS. True (default) keeps the fallback; False propagates the error.

  • preserve_lock_file (bool) – for native locks (AsyncFileLock), whether filelock promises not to unlink the lock pathname on release. False (default) keeps each backend’s cleanup; True keeps a stable file identity (Windows skips its unlink, Unix refuses the ENOSYS soft fallback). AsyncSoftFileLock rejects True.

  • on_acquired (Callable[[int], None] | None) – for native locks (AsyncFileLock), a callable invoked with the borrowed lock descriptor once per physical acquisition, after the lock is held but before acquire() returns. With run_in_executor=True (the default) it runs in the backend executor. It must not close or unlock the descriptor; a raise rolls the acquisition back. AsyncSoftFileLock rejects it.

  • loop (AbstractEventLoop | None) – The event loop to use. If not specified, the running event loop will be used.

  • run_in_executor (bool) – If this is set to True then the lock will be acquired in an executor.

  • executor (Executor | None) – The executor to use. If not specified, the default executor will be used.

class filelock.AsyncSoftReadWriteLock(lock_file, timeout=-1, *, blocking=True, is_singleton=True, heartbeat_interval=30.0, stale_threshold=None, poll_interval=0.25, loop=None, executor=None)[source]

Bases: object

Async wrapper around SoftReadWriteLock for asyncio applications.

The sync class’s blocking filesystem operations run on a thread pool via loop.run_in_executor(). The underlying SoftReadWriteLock handles reentrancy, upgrade/downgrade rules, fork handling, heartbeat and TTL stale detection, and singleton behavior.

Parameters:
  • lock_file (str | PathLike[str]) – path to the lock file; sidecar state/write/readers live next to it

  • timeout (float) – maximum wait time in seconds; -1 means block indefinitely

  • blocking (bool) – if False, raise Timeout immediately on contention

  • is_singleton (bool) – if True, reuse existing SoftReadWriteLock instances per resolved path

  • heartbeat_interval (float) – seconds between heartbeat refreshes; default 30 s

  • stale_threshold (float | None) – seconds of mtime inactivity before a marker is stale; defaults to 3 * heartbeat_interval

  • poll_interval (float) – seconds between acquire retries under contention; default 0.25 s

  • loop (AbstractEventLoop | None) – event loop for run_in_executor; None uses the running loop

  • executor (Executor | None) – executor for run_in_executor; None uses the default executor

Added in version 3.27.0.

property lock_file

The path to the lock file passed to the constructor.

property timeout

The default timeout applied when acquire_read / acquire_write is called without one.

property blocking

Whether acquire_* defaults to blocking; False makes contention raise immediately.

property loop

The event loop used for run_in_executor, or None for the running loop.

property executor

The executor used for run_in_executor, or None for the default executor.

read_lock(timeout=None, *, blocking=None)[source]

Async context manager that acquires and releases a shared read lock.

Parameters:
  • timeout (float | None) – maximum wait time in seconds, or None to use the instance default

  • blocking (bool | None) – if False, raise Timeout immediately; None uses the instance default

Raises:
  • RuntimeError – if a write lock is already held on this instance

  • Timeout – if the lock cannot be acquired within timeout seconds

Return type:

AsyncGenerator[None]

write_lock(timeout=None, *, blocking=None)[source]

Async context manager that acquires and releases an exclusive write lock.

Parameters:
  • timeout (float | None) – maximum wait time in seconds, or None to use the instance default

  • blocking (bool | None) – if False, raise Timeout immediately; None uses the instance default

Raises:
  • RuntimeError – if a read lock is already held, or a write lock is held by a different thread

  • Timeout – if the lock cannot be acquired within timeout seconds

Return type:

AsyncGenerator[None]

async acquire_read(timeout=None, *, blocking=None)[source]

Acquire a shared read lock.

See SoftReadWriteLock.acquire_read() for reentrancy / upgrade / fork semantics. The blocking work runs inside run_in_executor so other coroutines on the same loop keep progressing while this call waits.

Parameters:
  • timeout (float | None) – maximum wait time in seconds, or None to use the instance default

  • blocking (bool | None) – if False, raise Timeout immediately; None uses the instance default

Return type:

AsyncAcquireSoftReadWriteReturnProxy

Returns:

a proxy usable as an async context manager to release the lock

Raises:
  • RuntimeError – if a write lock is already held, if this instance was invalidated by os.fork(), or if close() was called

  • Timeout – if the lock cannot be acquired within timeout seconds

async acquire_write(timeout=None, *, blocking=None)[source]

Acquire an exclusive write lock.

See SoftReadWriteLock.acquire_write() for the two-phase writer-preferring semantics. The blocking work runs inside run_in_executor.

Parameters:
  • timeout (float | None) – maximum wait time in seconds, or None to use the instance default

  • blocking (bool | None) – if False, raise Timeout immediately; None uses the instance default

Return type:

AsyncAcquireSoftReadWriteReturnProxy

Returns:

a proxy usable as an async context manager to release the lock

Raises:
  • RuntimeError – if a read lock is already held, if a write lock is held by a different thread, if this instance was invalidated by os.fork(), or if close() was called

  • Timeout – if the lock cannot be acquired within timeout seconds

async release(*, force=False)[source]

Release one level of the current lock.

Parameters:

force (bool) – if True, release the lock completely regardless of the current lock level

Raises:

RuntimeError – if no lock is currently held and force is False

Return type:

None

async close()[source]

Release any held lock and release the underlying filesystem resources. Idempotent.

Return type:

None

class filelock.AsyncStrictSoftFileLock(lock_file, timeout=-1, mode=-1, thread_local=False, *, blocking=True, is_singleton=False, poll_interval=0.05, lifetime=None, context_error_policy='chain', close_error_policy='default', fallback_to_soft=True, preserve_lock_file=False, on_acquired=None, loop=None, run_in_executor=True, executor=None)[source]

Bases: StrictSoftFileLock, BaseAsyncFileLock

Run strict owner-claim locking without blocking the event loop.

Create a new lock object.

Parameters:
  • lock_file (str | PathLike[str]) – path to the file

  • timeout (float) – default timeout when acquiring the lock, in seconds. It will be used as fallback value in the acquire method, if no timeout value (None) is given. If you want to disable the timeout, set it to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.

  • mode (int) – file permissions for the lockfile. When not specified, the OS controls permissions via umask and default ACLs, preserving POSIX default ACL inheritance in shared directories.

  • thread_local (bool) – Whether this object’s internal context should be thread local or not. If this is set to False then the lock will be reentrant across threads. When True (the default), all fields of the lock’s internal context are per-thread, including the configuration values poll_interval, timeout, blocking, mode, and lifetime. Setting one of these properties from one thread does not change the value seen by another thread; threads that did not perform the write continue to see the value supplied at construction time. mode has no setter, so construction is the only place it is ever set. If you need configuration values to be visible across threads, construct the lock with thread_local=False.

  • blocking (bool) – whether the lock should be blocking or not

  • is_singleton (bool) – If this is set to True then only one instance of this class will be created per lock file. This is useful if you want to use the lock object for reentrant locking without needing to pass the same object around.

  • poll_interval (float) – default interval for polling the lock file, in seconds. It will be used as fallback value in the acquire method, if no poll_interval value (None) is given.

  • lifetime (float | None) – for AsyncSoftFileLock, the age in seconds after which a waiting process may delete the marker, even while its holder remains alive. This legacy expiry mode does not provide strict mutual exclusion. None (the default) disables age-based expiry. Native OS locks (AsyncFileLock) cannot be revoked by file age and ignore a non-None lifetime with a warning.

  • context_error_policy (Literal['chain', 'group']) – how a context manager reconciles a failure in its body with a failure while releasing on exit. "chain" (the default) keeps Python’s behavior: the release error propagates with the body error in its __context__. "group" raises a BaseExceptionGroup holding the body error first and the release error second, so neither hides the other.

  • close_error_policy (Literal['default', 'raise', 'suppress']) – for native locks (AsyncFileLock), what to do with an os.close failure after the OS unlock has already committed. "default" keeps each platform’s historical behavior, "raise" always propagates the OSError, and "suppress" always ignores it.

  • fallback_to_soft (bool) – for AsyncFileLock, whether to fall back to soft existence locking when flock returns ENOSYS. True (default) keeps the fallback; False propagates the error.

  • preserve_lock_file (bool) – for native locks (AsyncFileLock), whether filelock promises not to unlink the lock pathname on release. False (default) keeps each backend’s cleanup; True keeps a stable file identity (Windows skips its unlink, Unix refuses the ENOSYS soft fallback). AsyncSoftFileLock rejects True.

  • on_acquired (Callable[[int], None] | None) – for native locks (AsyncFileLock), a callable invoked with the borrowed lock descriptor once per physical acquisition, after the lock is held but before acquire() returns. With run_in_executor=True (the default) it runs in the backend executor. It must not close or unlock the descriptor; a raise rolls the acquisition back. AsyncSoftFileLock rejects it.

  • loop (AbstractEventLoop | None) – The event loop to use. If not specified, the running event loop will be used.

  • run_in_executor (bool) – If this is set to True then the lock will be acquired in an executor.

  • executor (Executor | None) – The executor to use. If not specified, the default executor will be used.

class filelock.AsyncUnixFileLock(lock_file, timeout=-1, mode=-1, thread_local=False, *, blocking=True, is_singleton=False, poll_interval=0.05, lifetime=None, context_error_policy='chain', close_error_policy='default', fallback_to_soft=True, preserve_lock_file=False, on_acquired=None, loop=None, run_in_executor=True, executor=None)[source]

Bases: UnixFileLock, BaseAsyncFileLock

Uses the fcntl.flock() to hard lock the lock file on unix systems.

Create a new lock object.

Parameters:
  • lock_file (str | PathLike[str]) – path to the file

  • timeout (float) – default timeout when acquiring the lock, in seconds. It will be used as fallback value in the acquire method, if no timeout value (None) is given. If you want to disable the timeout, set it to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.

  • mode (int) – file permissions for the lockfile. When not specified, the OS controls permissions via umask and default ACLs, preserving POSIX default ACL inheritance in shared directories.

  • thread_local (bool) – Whether this object’s internal context should be thread local or not. If this is set to False then the lock will be reentrant across threads. When True (the default), all fields of the lock’s internal context are per-thread, including the configuration values poll_interval, timeout, blocking, mode, and lifetime. Setting one of these properties from one thread does not change the value seen by another thread; threads that did not perform the write continue to see the value supplied at construction time. mode has no setter, so construction is the only place it is ever set. If you need configuration values to be visible across threads, construct the lock with thread_local=False.

  • blocking (bool) – whether the lock should be blocking or not

  • is_singleton (bool) – If this is set to True then only one instance of this class will be created per lock file. This is useful if you want to use the lock object for reentrant locking without needing to pass the same object around.

  • poll_interval (float) – default interval for polling the lock file, in seconds. It will be used as fallback value in the acquire method, if no poll_interval value (None) is given.

  • lifetime (float | None) – for AsyncSoftFileLock, the age in seconds after which a waiting process may delete the marker, even while its holder remains alive. This legacy expiry mode does not provide strict mutual exclusion. None (the default) disables age-based expiry. Native OS locks (AsyncFileLock) cannot be revoked by file age and ignore a non-None lifetime with a warning.

  • context_error_policy (Literal['chain', 'group']) – how a context manager reconciles a failure in its body with a failure while releasing on exit. "chain" (the default) keeps Python’s behavior: the release error propagates with the body error in its __context__. "group" raises a BaseExceptionGroup holding the body error first and the release error second, so neither hides the other.

  • close_error_policy (Literal['default', 'raise', 'suppress']) – for native locks (AsyncFileLock), what to do with an os.close failure after the OS unlock has already committed. "default" keeps each platform’s historical behavior, "raise" always propagates the OSError, and "suppress" always ignores it.

  • fallback_to_soft (bool) – for AsyncFileLock, whether to fall back to soft existence locking when flock returns ENOSYS. True (default) keeps the fallback; False propagates the error.

  • preserve_lock_file (bool) – for native locks (AsyncFileLock), whether filelock promises not to unlink the lock pathname on release. False (default) keeps each backend’s cleanup; True keeps a stable file identity (Windows skips its unlink, Unix refuses the ENOSYS soft fallback). AsyncSoftFileLock rejects True.

  • on_acquired (Callable[[int], None] | None) – for native locks (AsyncFileLock), a callable invoked with the borrowed lock descriptor once per physical acquisition, after the lock is held but before acquire() returns. With run_in_executor=True (the default) it runs in the backend executor. It must not close or unlock the descriptor; a raise rolls the acquisition back. AsyncSoftFileLock rejects it.

  • loop (AbstractEventLoop | None) – The event loop to use. If not specified, the running event loop will be used.

  • run_in_executor (bool) – If this is set to True then the lock will be acquired in an executor.

  • executor (Executor | None) – The executor to use. If not specified, the default executor will be used.

class filelock.AsyncWindowsFileLock(lock_file, timeout=-1, mode=-1, thread_local=False, *, blocking=True, is_singleton=False, poll_interval=0.05, lifetime=None, context_error_policy='chain', close_error_policy='default', fallback_to_soft=True, preserve_lock_file=False, on_acquired=None, loop=None, run_in_executor=True, executor=None)[source]

Bases: WindowsFileLock, BaseAsyncFileLock

Uses the msvcrt.locking() to hard lock the lock file on windows systems.

Create a new lock object.

Parameters:
  • lock_file (str | PathLike[str]) – path to the file

  • timeout (float) – default timeout when acquiring the lock, in seconds. It will be used as fallback value in the acquire method, if no timeout value (None) is given. If you want to disable the timeout, set it to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.

  • mode (int) – file permissions for the lockfile. When not specified, the OS controls permissions via umask and default ACLs, preserving POSIX default ACL inheritance in shared directories.

  • thread_local (bool) – Whether this object’s internal context should be thread local or not. If this is set to False then the lock will be reentrant across threads. When True (the default), all fields of the lock’s internal context are per-thread, including the configuration values poll_interval, timeout, blocking, mode, and lifetime. Setting one of these properties from one thread does not change the value seen by another thread; threads that did not perform the write continue to see the value supplied at construction time. mode has no setter, so construction is the only place it is ever set. If you need configuration values to be visible across threads, construct the lock with thread_local=False.

  • blocking (bool) – whether the lock should be blocking or not

  • is_singleton (bool) – If this is set to True then only one instance of this class will be created per lock file. This is useful if you want to use the lock object for reentrant locking without needing to pass the same object around.

  • poll_interval (float) – default interval for polling the lock file, in seconds. It will be used as fallback value in the acquire method, if no poll_interval value (None) is given.

  • lifetime (float | None) – for AsyncSoftFileLock, the age in seconds after which a waiting process may delete the marker, even while its holder remains alive. This legacy expiry mode does not provide strict mutual exclusion. None (the default) disables age-based expiry. Native OS locks (AsyncFileLock) cannot be revoked by file age and ignore a non-None lifetime with a warning.

  • context_error_policy (Literal['chain', 'group']) – how a context manager reconciles a failure in its body with a failure while releasing on exit. "chain" (the default) keeps Python’s behavior: the release error propagates with the body error in its __context__. "group" raises a BaseExceptionGroup holding the body error first and the release error second, so neither hides the other.

  • close_error_policy (Literal['default', 'raise', 'suppress']) – for native locks (AsyncFileLock), what to do with an os.close failure after the OS unlock has already committed. "default" keeps each platform’s historical behavior, "raise" always propagates the OSError, and "suppress" always ignores it.

  • fallback_to_soft (bool) – for AsyncFileLock, whether to fall back to soft existence locking when flock returns ENOSYS. True (default) keeps the fallback; False propagates the error.

  • preserve_lock_file (bool) – for native locks (AsyncFileLock), whether filelock promises not to unlink the lock pathname on release. False (default) keeps each backend’s cleanup; True keeps a stable file identity (Windows skips its unlink, Unix refuses the ENOSYS soft fallback). AsyncSoftFileLock rejects True.

  • on_acquired (Callable[[int], None] | None) – for native locks (AsyncFileLock), a callable invoked with the borrowed lock descriptor once per physical acquisition, after the lock is held but before acquire() returns. With run_in_executor=True (the default) it runs in the backend executor. It must not close or unlock the descriptor; a raise rolls the acquisition back. AsyncSoftFileLock rejects it.

  • loop (AbstractEventLoop | None) – The event loop to use. If not specified, the running event loop will be used.

  • run_in_executor (bool) – If this is set to True then the lock will be acquired in an executor.

  • executor (Executor | None) – The executor to use. If not specified, the default executor will be used.

class filelock.BaseAsyncFileLock(lock_file, timeout=-1, mode=-1, thread_local=False, *, blocking=True, is_singleton=False, poll_interval=0.05, lifetime=None, context_error_policy='chain', close_error_policy='default', fallback_to_soft=True, preserve_lock_file=False, on_acquired=None, loop=None, run_in_executor=True, executor=None)[source]

Bases: BaseFileLock

Base class for asynchronous file locks.

Added in version 3.15.0.

Create a new lock object.

Parameters:
  • lock_file (str | PathLike[str]) – path to the file

  • timeout (float) – default timeout when acquiring the lock, in seconds. It will be used as fallback value in the acquire method, if no timeout value (None) is given. If you want to disable the timeout, set it to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.

  • mode (int) – file permissions for the lockfile. When not specified, the OS controls permissions via umask and default ACLs, preserving POSIX default ACL inheritance in shared directories.

  • thread_local (bool) – Whether this object’s internal context should be thread local or not. If this is set to False then the lock will be reentrant across threads. When True (the default), all fields of the lock’s internal context are per-thread, including the configuration values poll_interval, timeout, blocking, mode, and lifetime. Setting one of these properties from one thread does not change the value seen by another thread; threads that did not perform the write continue to see the value supplied at construction time. mode has no setter, so construction is the only place it is ever set. If you need configuration values to be visible across threads, construct the lock with thread_local=False.

  • blocking (bool) – whether the lock should be blocking or not

  • is_singleton (bool) – If this is set to True then only one instance of this class will be created per lock file. This is useful if you want to use the lock object for reentrant locking without needing to pass the same object around.

  • poll_interval (float) – default interval for polling the lock file, in seconds. It will be used as fallback value in the acquire method, if no poll_interval value (None) is given.

  • lifetime (float | None) – for AsyncSoftFileLock, the age in seconds after which a waiting process may delete the marker, even while its holder remains alive. This legacy expiry mode does not provide strict mutual exclusion. None (the default) disables age-based expiry. Native OS locks (AsyncFileLock) cannot be revoked by file age and ignore a non-None lifetime with a warning.

  • context_error_policy (Literal['chain', 'group']) – how a context manager reconciles a failure in its body with a failure while releasing on exit. "chain" (the default) keeps Python’s behavior: the release error propagates with the body error in its __context__. "group" raises a BaseExceptionGroup holding the body error first and the release error second, so neither hides the other.

  • close_error_policy (Literal['default', 'raise', 'suppress']) – for native locks (AsyncFileLock), what to do with an os.close failure after the OS unlock has already committed. "default" keeps each platform’s historical behavior, "raise" always propagates the OSError, and "suppress" always ignores it.

  • fallback_to_soft (bool) – for AsyncFileLock, whether to fall back to soft existence locking when flock returns ENOSYS. True (default) keeps the fallback; False propagates the error.

  • preserve_lock_file (bool) – for native locks (AsyncFileLock), whether filelock promises not to unlink the lock pathname on release. False (default) keeps each backend’s cleanup; True keeps a stable file identity (Windows skips its unlink, Unix refuses the ENOSYS soft fallback). AsyncSoftFileLock rejects True.

  • on_acquired (Callable[[int], None] | None) – for native locks (AsyncFileLock), a callable invoked with the borrowed lock descriptor once per physical acquisition, after the lock is held but before acquire() returns. With run_in_executor=True (the default) it runs in the backend executor. It must not close or unlock the descriptor; a raise rolls the acquisition back. AsyncSoftFileLock rejects it.

  • loop (AbstractEventLoop | None) – The event loop to use. If not specified, the running event loop will be used.

  • run_in_executor (bool) – If this is set to True then the lock will be acquired in an executor.

  • executor (Executor | None) – The executor to use. If not specified, the default executor will be used.

property run_in_executor

Whether run in executor.

property executor

The executor.

property loop

The event loop.

async acquire(timeout=None, poll_interval=None, *, blocking=None, cancel_check=None)[source]

Try to acquire the file lock.

Parameters:
  • timeout (float | None) – maximum wait time for acquiring the lock, None means use the default timeout is and if timeout < 0, there is no timeout and this method will block until the lock could be acquired

  • poll_interval (float | None) – interval of trying to acquire the lock file, None means use the default poll_interval

  • blocking (bool | None) – defaults to True. If False, function will return immediately if it cannot obtain a lock on the first attempt. Otherwise, this method will block until the timeout expires or the lock is acquired.

  • cancel_check (Callable[[], bool] | None) – a callable returning True when the acquisition should be canceled. Checked on each poll iteration. When triggered, raises Timeout just like an expired timeout.

Return type:

AsyncAcquireReturnProxy

Returns:

a context object that will unlock the file when the context is exited

Raises:

Timeout – if fails to acquire lock within the timeout period

# You can use this method in the context manager (recommended)
with lock.acquire():
    pass

# Or use an equivalent try-finally construct:
lock.acquire()
try:
    pass
finally:
    lock.release()
async release(force=False)[source]

Release the file lock. The lock is only completely released when the lock counter reaches 0. The lock file itself may be deleted automatically, the behavior is platform-specific.

Parameters:

force (bool) – If true, the lock counter is ignored and the lock is released in every case.

Return type:

None

class filelock.BaseFileLock(lock_file, timeout=-1, mode=-1, thread_local=True, *, blocking=True, is_singleton=False, poll_interval=0.05, lifetime=None, context_error_policy='chain', close_error_policy='default', fallback_to_soft=True, preserve_lock_file=False, on_acquired=None)[source]

Bases: ContextDecorator

Abstract base class for a file lock object.

Provides the common reentrant API and state management. Subclasses implement the locking mechanism (UnixFileLock, WindowsFileLock, SoftFileLock).

Create a new lock object.

Parameters:
  • lock_file (str | PathLike[str]) – path to the file

  • timeout (float) – default timeout when acquiring the lock, in seconds. It will be used as fallback value in the acquire method, if no timeout value (None) is given. If you want to disable the timeout, set it to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.

  • mode (int) – file permissions for the lockfile. When not specified, the OS controls permissions via umask and default ACLs, preserving POSIX default ACL inheritance in shared directories.

  • thread_local (bool) – Whether this object’s internal context should be thread local or not. If this is set to False then the lock will be reentrant across threads. When True (the default), all fields of the lock’s internal context are per-thread, including the configuration values poll_interval, timeout, blocking, mode, and lifetime. Setting one of these properties from one thread does not change the value seen by another thread; threads that did not perform the write continue to see the value supplied at construction time. mode has no setter, so construction is the only place it is ever set. If you need configuration values to be visible across threads, construct the lock with thread_local=False.

  • blocking (bool) – whether the lock should be blocking or not

  • is_singleton (bool) – If this is set to True then only one instance of this class will be created per lock file. This is useful if you want to use the lock object for reentrant locking without needing to pass the same object around.

  • poll_interval (float) – default interval for polling the lock file, in seconds. It will be used as fallback value in the acquire method, if no poll_interval value (None) is given.

  • lifetime (float | None) – for SoftFileLock, the age in seconds after which a waiting process may delete the marker, even while its holder remains alive. This legacy expiry mode does not provide strict mutual exclusion. None (the default) disables age-based expiry. Native OS locks (FileLock) cannot be revoked by file age and ignore a non-None lifetime with a warning.

  • context_error_policy (Literal['chain', 'group']) – how a context manager reconciles a failure in its body with a failure while releasing on exit. "chain" (the default) keeps Python’s behavior: the release error propagates with the body error in its __context__. "group" raises a BaseExceptionGroup holding the body error first and the release error second, so neither hides the other.

  • close_error_policy (Literal['default', 'raise', 'suppress']) – what to do with an os.close failure after relinquishing descriptor ownership. "default" keeps each backend’s historical behavior (Unix native locks drop a FUSE/Docker EIO; Windows native locks and SoftFileLock propagate); "raise" always propagates the OSError; "suppress" always ignores it. Held state is released either way. It does not affect unlock failures or lock-file deletion.

  • fallback_to_soft (bool) – for UnixFileLock, whether to switch to SoftFileLock when the filesystem’s flock returns ENOSYS. True (the default) keeps the historical fallback; False fails closed, letting the ENOSYS propagate so a caller that needs kernel-enforced locking is never silently downgraded. It has no effect on Windows or SoftFileLock.

  • preserve_lock_file (bool) – for native locks (FileLock), whether filelock promises not to unlink the lock pathname on release. False (the default) keeps each backend’s cleanup: Windows removes the lock file, Unix already leaves it. True keeps a stable file identity for ACLs, auditing, and holder metadata: Windows skips its post-release unlink and Unix refuses to enter the ENOSYS soft fallback (which releases by unlinking). SoftFileLock rejects True. The promise covers filelock’s own release path only; it cannot stop another process or the filesystem from removing the pathname.

  • on_acquired (Callable[[int], None] | None) – for native locks (FileLock), a callable invoked with the borrowed lock descriptor once per physical acquisition, after filelock holds the native lock and finished backend initialization but before acquire() returns. Recursive acquisitions do not call it again. The callback may read, write, seek, truncate, or set metadata through os on the descriptor, but must not close, unlock, or take ownership of it, and filelock does not fsync its writes. If it raises, filelock releases the lock and re-raises. SoftFileLock rejects the hook.

is_thread_local()[source]
Return type:

bool

Returns:

a flag indicating if this lock is thread local or not

property is_singleton

A flag indicating if this lock is singleton or not.

Added in version 3.13.0.

property context_error_policy

How a context manager reconciles a body failure with a release failure on exit.

Added in version 3.30.0.

property close_error_policy

What a lock does with an os.close failure after relinquishing descriptor ownership.

Added in version 3.30.0.

property fallback_to_soft

Whether a FileLock falls back to SoftFileLock when the filesystem lacks flock.

Only UnixFileLock acts on it: when False an ENOSYS from flock propagates instead of switching to existence-lock semantics.

Added in version 3.30.0.

property preserve_lock_file

Whether filelock promises not to unlink the lock pathname on release.

When True, Windows skips its post-release unlink and Unix refuses the ENOSYS soft fallback. SoftFileLock rejects True because unlinking its marker is how it releases.

Added in version 3.30.0.

property on_acquired

The callback run with the borrowed lock descriptor once per physical acquisition, or None.

Native locks only. It runs after the native lock is held and backend initialization finished, before acquire() returns; a raise rolls back the acquisition. SoftFileLock rejects it.

Added in version 3.30.0.

property lock_file

Path to the lock file.

property timeout

The default timeout value, in seconds.

Added in version 2.0.0.

property blocking

Whether the locking is blocking or not.

Added in version 3.14.0.

property poll_interval

The default polling interval, in seconds.

Added in version 3.24.0.

property lifetime

The soft marker age in seconds that permits expiry, or None to disable age-based expiry.

A non-None value permits a waiter to enter while the previous holder remains active, so it does not provide strict mutual exclusion. Native locks ignore the value with a warning.

Added in version 3.24.0.

property mode

The file permissions for the lockfile.

property has_explicit_mode

Whether the file permissions were explicitly set.

property is_locked

A boolean indicating if the lock file is holding the lock currently.

Changed in version 2.0.0: This was previously a method and is now a property.

property lock_counter

The number of times this lock has been acquired (but not yet released).

acquire(timeout=None, poll_interval=None, *, poll_intervall=None, blocking=None, cancel_check=None)[source]

Try to acquire the file lock.

Parameters:
  • timeout (float | None) – maximum wait time for acquiring the lock, None means use the default timeout is and if timeout < 0, there is no timeout and this method will block until the lock could be acquired

  • poll_interval (float | None) – interval of trying to acquire the lock file, None means use the default poll_interval

  • poll_intervall (float | None) – deprecated, kept for backwards compatibility, use poll_interval instead

  • blocking (bool | None) – defaults to True. If False, function will return immediately if it cannot obtain a lock on the first attempt. Otherwise, this method will block until the timeout expires or the lock is acquired.

  • cancel_check (Callable[[], bool] | None) – a callable returning True when the acquisition should be canceled. Checked on each poll iteration. When triggered, raises Timeout just like an expired timeout.

Return type:

AcquireReturnProxy

Returns:

a context object that will unlock the file when the context is exited

Raises:

Timeout – if fails to acquire lock within the timeout period

# You can use this method in the context manager (recommended)
with lock.acquire():
    pass

# Or use an equivalent try-finally construct:
lock.acquire()
try:
    pass
finally:
    lock.release()

Changed in version 2.0.0: This method returns now a proxy object instead of self, so that it can be used in a with statement without side effects.

release(force=False)[source]

Release the file lock. The lock is only completely released when the lock counter reaches 0. The lock file itself may be deleted automatically, the behavior is platform-specific.

Parameters:

force (bool) – If true, the lock counter is ignored and the lock is released in every case.

Return type:

None

filelock.FileLock

Alias for the lock, which should be used for the current platform.

class filelock.LeaseCompromise(lock_file, token, reason, error=None)[source]

Bases: object

Why a held lease stopped being this process’s to hold.

lock_file
token
reason
error = None
exception filelock.LeaseSettingsMismatch[source]

Bases: ValueError

A lease contender disagrees with the published claim about how long the lease lasts.

class filelock.LockOptions[source]

Bases: TypedDict

Every option the metaclass forwards, so a subclass adding its own can still type what it passes through.

timeout
mode
thread_local
blocking
is_singleton
poll_interval
lifetime
context_error_policy
close_error_policy
fallback_to_soft
preserve_lock_file
on_acquired
class filelock.MarkerSoftFileLock(lock_file, timeout=-1, mode=-1, thread_local=True, *, blocking=True, is_singleton=False, poll_interval=0.05, lifetime=None, context_error_policy='chain', close_error_policy='default', fallback_to_soft=True, preserve_lock_file=False, on_acquired=None)[source]

Bases: SoftFileLock

An existence lock whose marker carries a protocol 2 owner record.

Create a new lock object.

Parameters:
  • lock_file (str | PathLike[str]) – path to the file

  • timeout (float) – default timeout when acquiring the lock, in seconds. It will be used as fallback value in the acquire method, if no timeout value (None) is given. If you want to disable the timeout, set it to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.

  • mode (int) – file permissions for the lockfile. When not specified, the OS controls permissions via umask and default ACLs, preserving POSIX default ACL inheritance in shared directories.

  • thread_local (bool) – Whether this object’s internal context should be thread local or not. If this is set to False then the lock will be reentrant across threads. When True (the default), all fields of the lock’s internal context are per-thread, including the configuration values poll_interval, timeout, blocking, mode, and lifetime. Setting one of these properties from one thread does not change the value seen by another thread; threads that did not perform the write continue to see the value supplied at construction time. mode has no setter, so construction is the only place it is ever set. If you need configuration values to be visible across threads, construct the lock with thread_local=False.

  • blocking (bool) – whether the lock should be blocking or not

  • is_singleton (bool) – If this is set to True then only one instance of this class will be created per lock file. This is useful if you want to use the lock object for reentrant locking without needing to pass the same object around.

  • poll_interval (float) – default interval for polling the lock file, in seconds. It will be used as fallback value in the acquire method, if no poll_interval value (None) is given.

  • lifetime (float | None) – for SoftFileLock, the age in seconds after which a waiting process may delete the marker, even while its holder remains alive. This legacy expiry mode does not provide strict mutual exclusion. None (the default) disables age-based expiry. Native OS locks (FileLock) cannot be revoked by file age and ignore a non-None lifetime with a warning.

  • context_error_policy (Literal['chain', 'group']) – how a context manager reconciles a failure in its body with a failure while releasing on exit. "chain" (the default) keeps Python’s behavior: the release error propagates with the body error in its __context__. "group" raises a BaseExceptionGroup holding the body error first and the release error second, so neither hides the other.

  • close_error_policy (Literal['default', 'raise', 'suppress']) – what to do with an os.close failure after relinquishing descriptor ownership. "default" keeps each backend’s historical behavior (Unix native locks drop a FUSE/Docker EIO; Windows native locks and SoftFileLock propagate); "raise" always propagates the OSError; "suppress" always ignores it. Held state is released either way. It does not affect unlock failures or lock-file deletion.

  • fallback_to_soft (bool) – for UnixFileLock, whether to switch to SoftFileLock when the filesystem’s flock returns ENOSYS. True (the default) keeps the historical fallback; False fails closed, letting the ENOSYS propagate so a caller that needs kernel-enforced locking is never silently downgraded. It has no effect on Windows or SoftFileLock.

  • preserve_lock_file (bool) – for native locks (FileLock), whether filelock promises not to unlink the lock pathname on release. False (the default) keeps each backend’s cleanup: Windows removes the lock file, Unix already leaves it. True keeps a stable file identity for ACLs, auditing, and holder metadata: Windows skips its post-release unlink and Unix refuses to enter the ENOSYS soft fallback (which releases by unlinking). SoftFileLock rejects True. The promise covers filelock’s own release path only; it cannot stop another process or the filesystem from removing the pathname.

  • on_acquired (Callable[[int], None] | None) – for native locks (FileLock), a callable invoked with the borrowed lock descriptor once per physical acquisition, after filelock holds the native lock and finished backend initialization but before acquire() returns. Recursive acquisitions do not call it again. The callback may read, write, seek, truncate, or set metadata through os on the descriptor, but must not close, unlock, or take ownership of it, and filelock does not fsync its writes. If it raises, filelock releases the lock and re-raises. SoftFileLock rejects the hook.

property owner

The owner named by the marker on disk.

Returns:

the published record, or None when no marker exists or its record is malformed or protocol 1

property pid

The PID of the process holding this lock, read from the marker.

Returns:

the PID, or None when no marker exists or its record is unreadable

property is_lock_held_by_us

Whether the marker on disk names this process.

Returns:

True when the marker’s PID and hostname match this process

force_break()[source]

Remove the marker whoever holds it, so a later contender can acquire.

Forced breaking voids mutual exclusion: the previous holder keeps running and keeps using whatever the lock protects. Reserve it for an operator clearing a marker whose holder is known to be gone.

Return type:

None

class filelock.OwnerRecord(pid, hostname, mode, token=None, lease_duration=None, start=None)[source]

Bases: NamedTuple

The owner published in a protocol 2 marker.

Create new instance of OwnerRecord(pid, hostname, mode, token, lease_duration, start)

pid

Alias for field number 0

hostname

Alias for field number 1

mode

Alias for field number 2

token

Alias for field number 3

lease_duration

Alias for field number 4

start

Alias for field number 5

class filelock.ReadWriteLock(lock_file, timeout=-1, *, blocking=True, is_singleton=True)[source]

Bases: object

Cross-process read-write lock backed by SQLite.

Allows concurrent shared readers or a single exclusive writer. The lock is reentrant within the same mode (multiple acquire_read calls nest, as do multiple acquire_write calls from the same thread), but upgrading from read to write or downgrading from write to read raises RuntimeError. Write locks are pinned to the thread that acquired them.

By default, is_singleton=True: calling ReadWriteLock(path) with the same resolved path returns the same instance. The path is handed to sqlite3.connect() as given, so a .db extension is a convention rather than a requirement; the filesystem must be one the active SQLite VFS supports.

Parameters:
  • lock_file (str | PathLike[str]) – path to the SQLite database file used as the lock

  • timeout (float) – maximum wait time in seconds; -1 means block indefinitely

  • blocking (bool) – if False, raise Timeout immediately when the lock is unavailable

  • is_singleton (bool) – if True, reuse existing instances for the same resolved path

Added in version 3.21.0.

classmethod get_lock(lock_file, timeout=-1, *, blocking=True)[source]

Return the singleton ReadWriteLock for lock_file.

Parameters:
  • lock_file (str | PathLike[str]) – path to the SQLite database file used as the lock

  • timeout (float) – maximum wait time in seconds; -1 means block indefinitely

  • blocking (bool) – if False, raise Timeout immediately when the lock is unavailable

Return type:

ReadWriteLock

Returns:

the singleton lock instance

Raises:

ValueError – if an instance already exists for this path with different timeout or blocking values

acquire_read(timeout=-1, *, blocking=True)[source]

Acquire a shared read lock.

If this instance already holds a read lock, the lock level is incremented (reentrant). Attempting to acquire a read lock while holding a write lock raises RuntimeError (downgrade not allowed).

Parameters:
  • timeout (float) – maximum wait time in seconds; -1 means block indefinitely

  • blocking (bool) – if False, raise Timeout immediately when the lock is unavailable

Return type:

AcquireReturnProxy

Returns:

a proxy that can be used as a context manager to release the lock

Raises:
  • RuntimeError – if a write lock is already held on this instance

  • Timeout – if the lock cannot be acquired within timeout seconds

acquire_write(timeout=-1, *, blocking=True)[source]

Acquire an exclusive write lock.

If this instance already holds a write lock from the same thread, the lock level is incremented (reentrant). Attempting to acquire a write lock while holding a read lock raises RuntimeError (upgrade not allowed). Write locks are pinned to the acquiring thread: a different thread trying to re-enter also raises RuntimeError.

Parameters:
  • timeout (float) – maximum wait time in seconds; -1 means block indefinitely

  • blocking (bool) – if False, raise Timeout immediately when the lock is unavailable

Return type:

AcquireReturnProxy

Returns:

a proxy that can be used as a context manager to release the lock

Raises:
  • RuntimeError – if a read lock is already held, or a write lock is held by a different thread

  • Timeout – if the lock cannot be acquired within timeout seconds

read_lock(timeout=None, *, blocking=None)[source]

Context manager that acquires and releases a shared read lock.

Falls back to instance defaults for timeout and blocking when None.

Parameters:
  • timeout (float | None) – maximum wait time in seconds, or None to use the instance default

  • blocking (bool | None) – if False, raise Timeout immediately; None uses the instance default

Return type:

Generator[None]

write_lock(timeout=None, *, blocking=None)[source]

Context manager that acquires and releases an exclusive write lock.

Falls back to instance defaults for timeout and blocking when None.

Parameters:
  • timeout (float | None) – maximum wait time in seconds, or None to use the instance default

  • blocking (bool | None) – if False, raise Timeout immediately; None uses the instance default

Return type:

Generator[None]

release(*, force=False)[source]

Release one level of the current lock.

When the lock level reaches zero the underlying SQLite transaction is rolled back, releasing the database lock.

Parameters:

force (bool) – if True, release the lock completely regardless of the current lock level

Raises:

RuntimeError – if no lock is currently held and force is False

Return type:

None

close()[source]

Release the lock (if held) and close the underlying SQLite connection.

After calling this method, the lock instance is no longer usable.

Return type:

None

class filelock.SoftFileLease(lock_file, *, lease_duration=30.0, heartbeat_interval=None, on_compromise=None, **kwargs)[source]

Bases: MarkerSoftFileLock

Existence lock whose claim expires, so a peer may take it while the previous holder still runs.

A lease trades mutual exclusion for progress. The holder publishes a claim and refreshes it every heartbeat_interval seconds; a contender takes the marker once it is lease_duration seconds stale. Nothing stops the expired holder: it keeps running, and it keeps using whatever the lock protects. Treat the lease as a hint about who should be working, not as a guarantee that only one worker is.

To make a protected resource reject a superseded holder, that resource must be linearizable and must fence on a monotonic generation it controls. token names a claim; it does not fence one. Where overlap is unacceptable, use StrictSoftFileLock instead.

Every contender for a path must agree on lease_duration. A contender that finds a claim published under a different duration raises LeaseSettingsMismatch rather than apply its own expiry to a peer that never agreed to it.

Expiry reclaims less on Windows, which refuses to rename or delete a file another process holds open. A peer there takes an expired claim only once the previous holder’s process exits and its handle closes; a holder that lives on but stops refreshing keeps the marker. Unix reclaims the marker either way.

on_compromise fires from the heartbeat thread when a refresh fails, or when the marker vanishes or names another owner. The holder should stop touching the protected resource when it runs. Because it runs on that thread, a release() inside it only takes effect when the lease was built with thread_local=False; the default thread-local context hides the claim from every thread but the one that acquired it, so the release does nothing. Signal the acquiring thread instead when the context stays thread-local.

Added in version 3.30.0.

Create a lease.

Parameters:
  • lease_duration (float) – seconds of marker staleness after which a contender may take the claim. Every contender for the path must pass the same value.

  • heartbeat_interval (float | None) – seconds between refreshes. Defaults to a third of lease_duration, leaving room for two missed refreshes before a peer may take the claim. Must be shorter than lease_duration.

  • on_compromise (Callable[[LeaseCompromise], None] | None) – called from the heartbeat thread with a LeaseCompromise when the claim is lost.

  • kwargs (Unpack[LockOptions]) – every other BaseFileLock option, timeout and mode among them. The metaclass passes them all by keyword, and taking them here lets AsyncSoftFileLease add the async plumbing a fixed signature would hide.

property lease_duration

The staleness in seconds after which a contender may take this claim.

property token

The token naming the claim this process published.

Returns:

the token while the lease is held, None otherwise. It identifies a claim; it does not fence one.

property compromise

The loss of claim the heartbeat observed.

Returns:

the LeaseCompromise, or None while the claim still holds

class filelock.SoftFileLock(lock_file, timeout=-1, mode=-1, thread_local=True, *, blocking=True, is_singleton=False, poll_interval=0.05, lifetime=None, context_error_policy='chain', close_error_policy='default', fallback_to_soft=True, preserve_lock_file=False, on_acquired=None)[source]

Bases: BaseFileLock

Cooperative file lock based on a shared existence marker.

Unlike UnixFileLock and WindowsFileLock, this lock does not use OS-level locking primitives. Instead, it creates the lock file with O_CREAT | O_EXCL and treats its existence as the lock indicator. The filesystem must provide coherent exclusive creation and directory updates to each participating process. A crash can leave the marker behind.

The marker contains the holder’s PID and hostname. A contender may remove it when it can no longer find a same-host process with that PID. A configured lifetime also permits removal based on marker age, including while the holder remains alive. Age-based expiry can overlap protected operations and does not provide strict mutual exclusion.

Create a new lock object.

Parameters:
  • lock_file (str | PathLike[str]) – path to the file

  • timeout (float) – default timeout when acquiring the lock, in seconds. It will be used as fallback value in the acquire method, if no timeout value (None) is given. If you want to disable the timeout, set it to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.

  • mode (int) – file permissions for the lockfile. When not specified, the OS controls permissions via umask and default ACLs, preserving POSIX default ACL inheritance in shared directories.

  • thread_local (bool) – Whether this object’s internal context should be thread local or not. If this is set to False then the lock will be reentrant across threads. When True (the default), all fields of the lock’s internal context are per-thread, including the configuration values poll_interval, timeout, blocking, mode, and lifetime. Setting one of these properties from one thread does not change the value seen by another thread; threads that did not perform the write continue to see the value supplied at construction time. mode has no setter, so construction is the only place it is ever set. If you need configuration values to be visible across threads, construct the lock with thread_local=False.

  • blocking (bool) – whether the lock should be blocking or not

  • is_singleton (bool) – If this is set to True then only one instance of this class will be created per lock file. This is useful if you want to use the lock object for reentrant locking without needing to pass the same object around.

  • poll_interval (float) – default interval for polling the lock file, in seconds. It will be used as fallback value in the acquire method, if no poll_interval value (None) is given.

  • lifetime (float | None) – for SoftFileLock, the age in seconds after which a waiting process may delete the marker, even while its holder remains alive. This legacy expiry mode does not provide strict mutual exclusion. None (the default) disables age-based expiry. Native OS locks (FileLock) cannot be revoked by file age and ignore a non-None lifetime with a warning.

  • context_error_policy (Literal['chain', 'group']) – how a context manager reconciles a failure in its body with a failure while releasing on exit. "chain" (the default) keeps Python’s behavior: the release error propagates with the body error in its __context__. "group" raises a BaseExceptionGroup holding the body error first and the release error second, so neither hides the other.

  • close_error_policy (Literal['default', 'raise', 'suppress']) – what to do with an os.close failure after relinquishing descriptor ownership. "default" keeps each backend’s historical behavior (Unix native locks drop a FUSE/Docker EIO; Windows native locks and SoftFileLock propagate); "raise" always propagates the OSError; "suppress" always ignores it. Held state is released either way. It does not affect unlock failures or lock-file deletion.

  • fallback_to_soft (bool) – for UnixFileLock, whether to switch to SoftFileLock when the filesystem’s flock returns ENOSYS. True (the default) keeps the historical fallback; False fails closed, letting the ENOSYS propagate so a caller that needs kernel-enforced locking is never silently downgraded. It has no effect on Windows or SoftFileLock.

  • preserve_lock_file (bool) – for native locks (FileLock), whether filelock promises not to unlink the lock pathname on release. False (the default) keeps each backend’s cleanup: Windows removes the lock file, Unix already leaves it. True keeps a stable file identity for ACLs, auditing, and holder metadata: Windows skips its post-release unlink and Unix refuses to enter the ENOSYS soft fallback (which releases by unlinking). SoftFileLock rejects True. The promise covers filelock’s own release path only; it cannot stop another process or the filesystem from removing the pathname.

  • on_acquired (Callable[[int], None] | None) – for native locks (FileLock), a callable invoked with the borrowed lock descriptor once per physical acquisition, after filelock holds the native lock and finished backend initialization but before acquire() returns. Recursive acquisitions do not call it again. The callback may read, write, seek, truncate, or set metadata through os on the descriptor, but must not close, unlock, or take ownership of it, and filelock does not fsync its writes. If it raises, filelock releases the lock and re-raises. SoftFileLock rejects the hook.

property pid

The PID of the process holding this lock, read from the lock file.

Returns:

the PID as an integer, or None if the lock file does not exist or cannot be parsed

property is_lock_held_by_us

Whether this lock is held by the current process.

Returns:

True if the lock file exists and names the current process’s PID and hostname

break_lock()[source]

Forcibly break the lock by removing the lock file, regardless of who holds it.

Return type:

None

exception filelock.SoftFileLockLifetimeWarning[source]

Bases: DeprecationWarning

The configured soft-lock lifetime permits overlapping live holders after expiry.

exception filelock.SoftFileLockProtocolError(lock_file, claim_name, reason)[source]

Bases: OSError

Raised when strict soft-lock state cannot be interpreted without risking overlap.

property lock_file

The requested lock path.

property claim_name

The claim that caused the error, if scanning identified one.

property reason

The protocol validation failure.

class filelock.SoftReadWriteLock(lock_file, timeout=-1, *, blocking=True, is_singleton=True, heartbeat_interval=30.0, stale_threshold=None, poll_interval=0.25)[source]

Bases: object

Cross-process and cross-host reader/writer lock built on SoftFileLock primitives.

Use this class instead of ReadWriteLock when the lock file lives on a network filesystem (NFS, Lustre with -o flock, HPC cluster shared storage). ReadWriteLock is backed by SQLite and cannot run on NFS because SQLite’s fcntl locking is unreliable there.

Layout on disk for a lock at foo.lock:

  • foo.lock.state — a SoftFileLock taken only during state transitions (microseconds).

  • foo.lock.write — writer marker; its presence means a writer is claiming or holding the lock.

  • foo.lock.readers/<host>.<pid>.<uuid> — one file per reader.

Each marker stores a random token (secrets.token_hex(16)), the holder’s pid, and the holder’s hostname. A daemon heartbeat thread refreshes mtime on every held marker. A marker whose mtime has not advanced in stale_threshold seconds may be evicted by any process on any host, giving correct behavior when a compute node crashes with a lock held.

Writer acquire is two-phase and writer-preferring: phase 1 claims .write (blocking any new reader), phase 2 waits for existing readers to drain. Writer starvation is impossible.

Reentrancy, upgrade/downgrade rules, thread pinning, and singleton caching by resolved path match ReadWriteLock.

Forking invalidates the inherited instance in the child so the child cannot double-own the lock with its parent; release() on that instance is a no-op, and the child must construct a new instance if it needs a lock.

Trust boundary: protects against same-UID non-cooperating processes (one host or cross-host) and same-host different-UID users via 0o600 / 0o700 permissions. Does not protect against root compromise, NTP tampering on same-UID cross-host nodes, or multi-tenant mounts where hostile co-tenants share the UID.

Parameters:
  • lock_file (str | PathLike[str]) – path to the lock file; sidecar state/write/readers live next to it

  • timeout (float) – maximum wait time in seconds; -1 means block indefinitely

  • blocking (bool) – if False, raise Timeout immediately on contention

  • is_singleton (bool) – if True, reuse existing instances for the same resolved path

  • heartbeat_interval (float) – seconds between heartbeat refreshes; default 30 s

  • stale_threshold (float | None) – seconds of mtime inactivity before a marker is stale; defaults to 3 * heartbeat_interval, matching etcd’s LeaseKeepAlive convention

  • poll_interval (float) – seconds between acquire retries under contention; default 0.25 s

Added in version 3.27.0.

read_lock(timeout=None, *, blocking=None)[source]

Context manager that acquires and releases a shared read lock.

Falls back to instance defaults for timeout and blocking when None.

Parameters:
  • timeout (float | None) – maximum wait time in seconds, or None to use the instance default

  • blocking (bool | None) – if False, raise Timeout immediately; None uses the instance default

Raises:
  • RuntimeError – if a write lock is already held on this instance

  • Timeout – if the lock cannot be acquired within timeout seconds

Return type:

Generator[None]

write_lock(timeout=None, *, blocking=None)[source]

Context manager that acquires and releases an exclusive write lock.

Falls back to instance defaults for timeout and blocking when None.

Parameters:
  • timeout (float | None) – maximum wait time in seconds, or None to use the instance default

  • blocking (bool | None) – if False, raise Timeout immediately; None uses the instance default

Raises:
  • RuntimeError – if a read lock is already held, or a write lock is held by a different thread

  • Timeout – if the lock cannot be acquired within timeout seconds

Return type:

Generator[None]

acquire_read(timeout=None, *, blocking=None)[source]

Acquire a shared read lock.

If this instance already holds a read lock, the lock level is incremented (reentrant). Attempting to acquire a read lock while holding a write lock raises RuntimeError (downgrade not allowed). On the 0→1 transition a daemon heartbeat thread is started that refreshes the reader marker’s mtime every heartbeat_interval seconds so peers on other hosts do not evict the marker as stale.

Parameters:
  • timeout (float | None) – maximum wait time in seconds, or None to use the instance default; -1 means block indefinitely

  • blocking (bool | None) – if False, raise Timeout immediately when the lock is unavailable; None uses the instance default

Return type:

AcquireReturnProxy

Returns:

a proxy that can be used as a context manager to release the lock

Raises:
  • RuntimeError – if a write lock is already held on this instance, if this instance was invalidated by os.fork(), or if close() was called

  • Timeout – if the lock cannot be acquired within timeout seconds

acquire_write(timeout=None, *, blocking=None)[source]

Acquire an exclusive write lock.

If this instance already holds a write lock from the same thread, the lock level is incremented (reentrant). Attempting to acquire a write lock while holding a read lock raises RuntimeError (upgrade not allowed). Write locks are pinned to the acquiring thread: a different thread trying to re-enter also raises RuntimeError.

Writer acquisition runs in two phases. Phase 1 atomically claims <path>.write via O_CREAT | O_EXCL, which immediately blocks any new reader on any host. Phase 2 waits for existing readers to drain. Writer starvation is impossible: new readers see <path>.write during phase 2 and wait behind the pending writer.

Parameters:
  • timeout (float | None) – maximum wait time in seconds, or None to use the instance default; -1 means block indefinitely

  • blocking (bool | None) – if False, raise Timeout immediately when the lock is unavailable; None uses the instance default

Return type:

AcquireReturnProxy

Returns:

a proxy that can be used as a context manager to release the lock

Raises:
  • RuntimeError – if a read lock is already held, if a write lock is held by a different thread, if this instance was invalidated by os.fork(), or if close() was called

  • Timeout – if the lock cannot be acquired within timeout seconds

classmethod get_lock(lock_file, timeout=-1, *, blocking=True)[source]

Return the singleton SoftReadWriteLock for lock_file.

Parameters:
  • lock_file (str | PathLike[str]) – path to the lock file; sidecar state/write/readers live next to it

  • timeout (float) – maximum wait time in seconds; -1 means block indefinitely

  • blocking (bool) – if False, raise Timeout immediately when the lock is unavailable

Return type:

SoftReadWriteLock

Returns:

the singleton lock instance

Raises:

ValueError – if an instance already exists for this path with different timeout or blocking values

close()[source]

Release any held lock and release internal filesystem resources.

Idempotent. After calling this method the instance can no longer acquire locks — subsequent acquires raise RuntimeError. A fork-invalidated instance is closed without raising.

Return type:

None

release(*, force=False)[source]

Release one level of the current lock.

When the lock level reaches zero the heartbeat thread is stopped and the held marker file is unlinked. On a fork-invalidated instance (that is, the child of a os.fork() call made while the parent held a lock) this method is a no-op so inherited with blocks can unwind cleanly in the child.

Parameters:

force (bool) – if True, release the lock completely regardless of the current lock level

Raises:

RuntimeError – if no lock is currently held and force is False

Return type:

None

class filelock.StrictSoftFileClaim(name, state, token, pid, hostname, start=None)[source]

Bases: object

One parsed strict soft-lock claim.

name
state
token
pid
hostname
start = None

The owner’s process start token, or None when the platform exposes no proven start time. A strict lock never reclaims a claim on its own, so this identifies the owner for tooling rather than driving any automatic break.

class filelock.StrictSoftFileLock(lock_file, timeout=-1, mode=-1, thread_local=True, *, blocking=True, is_singleton=False, poll_interval=0.05, lifetime=None, context_error_policy='chain', close_error_policy='default', fallback_to_soft=True, preserve_lock_file=False, on_acquired=None)[source]

Bases: BaseFileLock

Portable fail-closed lock based on immutable owner claims.

Create a new lock object.

Parameters:
  • lock_file (str | PathLike[str]) – path to the file

  • timeout (float) – default timeout when acquiring the lock, in seconds. It will be used as fallback value in the acquire method, if no timeout value (None) is given. If you want to disable the timeout, set it to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.

  • mode (int) – file permissions for the lockfile. When not specified, the OS controls permissions via umask and default ACLs, preserving POSIX default ACL inheritance in shared directories.

  • thread_local (bool) – Whether this object’s internal context should be thread local or not. If this is set to False then the lock will be reentrant across threads. When True (the default), all fields of the lock’s internal context are per-thread, including the configuration values poll_interval, timeout, blocking, mode, and lifetime. Setting one of these properties from one thread does not change the value seen by another thread; threads that did not perform the write continue to see the value supplied at construction time. mode has no setter, so construction is the only place it is ever set. If you need configuration values to be visible across threads, construct the lock with thread_local=False.

  • blocking (bool) – whether the lock should be blocking or not

  • is_singleton (bool) – If this is set to True then only one instance of this class will be created per lock file. This is useful if you want to use the lock object for reentrant locking without needing to pass the same object around.

  • poll_interval (float) – default interval for polling the lock file, in seconds. It will be used as fallback value in the acquire method, if no poll_interval value (None) is given.

  • lifetime (float | None) – for SoftFileLock, the age in seconds after which a waiting process may delete the marker, even while its holder remains alive. This legacy expiry mode does not provide strict mutual exclusion. None (the default) disables age-based expiry. Native OS locks (FileLock) cannot be revoked by file age and ignore a non-None lifetime with a warning.

  • context_error_policy (Literal['chain', 'group']) – how a context manager reconciles a failure in its body with a failure while releasing on exit. "chain" (the default) keeps Python’s behavior: the release error propagates with the body error in its __context__. "group" raises a BaseExceptionGroup holding the body error first and the release error second, so neither hides the other.

  • close_error_policy (Literal['default', 'raise', 'suppress']) – what to do with an os.close failure after relinquishing descriptor ownership. "default" keeps each backend’s historical behavior (Unix native locks drop a FUSE/Docker EIO; Windows native locks and SoftFileLock propagate); "raise" always propagates the OSError; "suppress" always ignores it. Held state is released either way. It does not affect unlock failures or lock-file deletion.

  • fallback_to_soft (bool) – for UnixFileLock, whether to switch to SoftFileLock when the filesystem’s flock returns ENOSYS. True (the default) keeps the historical fallback; False fails closed, letting the ENOSYS propagate so a caller that needs kernel-enforced locking is never silently downgraded. It has no effect on Windows or SoftFileLock.

  • preserve_lock_file (bool) – for native locks (FileLock), whether filelock promises not to unlink the lock pathname on release. False (the default) keeps each backend’s cleanup: Windows removes the lock file, Unix already leaves it. True keeps a stable file identity for ACLs, auditing, and holder metadata: Windows skips its post-release unlink and Unix refuses to enter the ENOSYS soft fallback (which releases by unlinking). SoftFileLock rejects True. The promise covers filelock’s own release path only; it cannot stop another process or the filesystem from removing the pathname.

  • on_acquired (Callable[[int], None] | None) – for native locks (FileLock), a callable invoked with the borrowed lock descriptor once per physical acquisition, after filelock holds the native lock and finished backend initialization but before acquire() returns. Recursive acquisitions do not call it again. The callback may read, write, seek, truncate, or set metadata through os on the descriptor, but must not close, unlock, or take ownership of it, and filelock does not fsync its writes. If it raises, filelock releases the lock and re-raises. SoftFileLock rejects the hook.

property claims

Published claims that block acquisition.

force_break(claim_name)[source]

Remove one named claim, allowing overlap if its owner still holds the protected resource.

Return type:

None

exception filelock.Timeout(lock_file)[source]

Bases: TimeoutError

Raised when the lock could not be acquired in timeout seconds.

property lock_file

The path of the file lock.

class filelock.UnixFileLock(lock_file, timeout=-1, mode=-1, thread_local=True, *, blocking=True, is_singleton=False, poll_interval=0.05, lifetime=None, context_error_policy='chain', close_error_policy='default', fallback_to_soft=True, preserve_lock_file=False, on_acquired=None)[source]

Bases: BaseFileLock

Uses the fcntl.flock() to hard lock the lock file on unix systems.

We leave the lock file in place after release. Unlinking a locked file on Unix splits waiters across inodes and breaks mutual exclusion for processes that coordinate via the same path.

Create a new lock object.

Parameters:
  • lock_file (str | PathLike[str]) – path to the file

  • timeout (float) – default timeout when acquiring the lock, in seconds. It will be used as fallback value in the acquire method, if no timeout value (None) is given. If you want to disable the timeout, set it to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.

  • mode (int) – file permissions for the lockfile. When not specified, the OS controls permissions via umask and default ACLs, preserving POSIX default ACL inheritance in shared directories.

  • thread_local (bool) – Whether this object’s internal context should be thread local or not. If this is set to False then the lock will be reentrant across threads. When True (the default), all fields of the lock’s internal context are per-thread, including the configuration values poll_interval, timeout, blocking, mode, and lifetime. Setting one of these properties from one thread does not change the value seen by another thread; threads that did not perform the write continue to see the value supplied at construction time. mode has no setter, so construction is the only place it is ever set. If you need configuration values to be visible across threads, construct the lock with thread_local=False.

  • blocking (bool) – whether the lock should be blocking or not

  • is_singleton (bool) – If this is set to True then only one instance of this class will be created per lock file. This is useful if you want to use the lock object for reentrant locking without needing to pass the same object around.

  • poll_interval (float) – default interval for polling the lock file, in seconds. It will be used as fallback value in the acquire method, if no poll_interval value (None) is given.

  • lifetime (float | None) – for SoftFileLock, the age in seconds after which a waiting process may delete the marker, even while its holder remains alive. This legacy expiry mode does not provide strict mutual exclusion. None (the default) disables age-based expiry. Native OS locks (FileLock) cannot be revoked by file age and ignore a non-None lifetime with a warning.

  • context_error_policy (Literal['chain', 'group']) – how a context manager reconciles a failure in its body with a failure while releasing on exit. "chain" (the default) keeps Python’s behavior: the release error propagates with the body error in its __context__. "group" raises a BaseExceptionGroup holding the body error first and the release error second, so neither hides the other.

  • close_error_policy (Literal['default', 'raise', 'suppress']) – what to do with an os.close failure after relinquishing descriptor ownership. "default" keeps each backend’s historical behavior (Unix native locks drop a FUSE/Docker EIO; Windows native locks and SoftFileLock propagate); "raise" always propagates the OSError; "suppress" always ignores it. Held state is released either way. It does not affect unlock failures or lock-file deletion.

  • fallback_to_soft (bool) – for UnixFileLock, whether to switch to SoftFileLock when the filesystem’s flock returns ENOSYS. True (the default) keeps the historical fallback; False fails closed, letting the ENOSYS propagate so a caller that needs kernel-enforced locking is never silently downgraded. It has no effect on Windows or SoftFileLock.

  • preserve_lock_file (bool) – for native locks (FileLock), whether filelock promises not to unlink the lock pathname on release. False (the default) keeps each backend’s cleanup: Windows removes the lock file, Unix already leaves it. True keeps a stable file identity for ACLs, auditing, and holder metadata: Windows skips its post-release unlink and Unix refuses to enter the ENOSYS soft fallback (which releases by unlinking). SoftFileLock rejects True. The promise covers filelock’s own release path only; it cannot stop another process or the filesystem from removing the pathname.

  • on_acquired (Callable[[int], None] | None) – for native locks (FileLock), a callable invoked with the borrowed lock descriptor once per physical acquisition, after filelock holds the native lock and finished backend initialization but before acquire() returns. Recursive acquisitions do not call it again. The callback may read, write, seek, truncate, or set metadata through os on the descriptor, but must not close, unlock, or take ownership of it, and filelock does not fsync its writes. If it raises, filelock releases the lock and re-raises. SoftFileLock rejects the hook.

class filelock.WindowsFileLock(lock_file, timeout=-1, mode=-1, thread_local=True, *, blocking=True, is_singleton=False, poll_interval=0.05, lifetime=None, context_error_policy='chain', close_error_policy='default', fallback_to_soft=True, preserve_lock_file=False, on_acquired=None)[source]

Bases: BaseFileLock

Uses LockFileEx to hard lock a byte range of the lock file on Windows systems.

Create a new lock object.

Parameters:
  • lock_file (str | PathLike[str]) – path to the file

  • timeout (float) – default timeout when acquiring the lock, in seconds. It will be used as fallback value in the acquire method, if no timeout value (None) is given. If you want to disable the timeout, set it to a negative value. A timeout of 0 means that there is exactly one attempt to acquire the file lock.

  • mode (int) – file permissions for the lockfile. When not specified, the OS controls permissions via umask and default ACLs, preserving POSIX default ACL inheritance in shared directories.

  • thread_local (bool) – Whether this object’s internal context should be thread local or not. If this is set to False then the lock will be reentrant across threads. When True (the default), all fields of the lock’s internal context are per-thread, including the configuration values poll_interval, timeout, blocking, mode, and lifetime. Setting one of these properties from one thread does not change the value seen by another thread; threads that did not perform the write continue to see the value supplied at construction time. mode has no setter, so construction is the only place it is ever set. If you need configuration values to be visible across threads, construct the lock with thread_local=False.

  • blocking (bool) – whether the lock should be blocking or not

  • is_singleton (bool) – If this is set to True then only one instance of this class will be created per lock file. This is useful if you want to use the lock object for reentrant locking without needing to pass the same object around.

  • poll_interval (float) – default interval for polling the lock file, in seconds. It will be used as fallback value in the acquire method, if no poll_interval value (None) is given.

  • lifetime (float | None) – for SoftFileLock, the age in seconds after which a waiting process may delete the marker, even while its holder remains alive. This legacy expiry mode does not provide strict mutual exclusion. None (the default) disables age-based expiry. Native OS locks (FileLock) cannot be revoked by file age and ignore a non-None lifetime with a warning.

  • context_error_policy (Literal['chain', 'group']) – how a context manager reconciles a failure in its body with a failure while releasing on exit. "chain" (the default) keeps Python’s behavior: the release error propagates with the body error in its __context__. "group" raises a BaseExceptionGroup holding the body error first and the release error second, so neither hides the other.

  • close_error_policy (Literal['default', 'raise', 'suppress']) – what to do with an os.close failure after relinquishing descriptor ownership. "default" keeps each backend’s historical behavior (Unix native locks drop a FUSE/Docker EIO; Windows native locks and SoftFileLock propagate); "raise" always propagates the OSError; "suppress" always ignores it. Held state is released either way. It does not affect unlock failures or lock-file deletion.

  • fallback_to_soft (bool) – for UnixFileLock, whether to switch to SoftFileLock when the filesystem’s flock returns ENOSYS. True (the default) keeps the historical fallback; False fails closed, letting the ENOSYS propagate so a caller that needs kernel-enforced locking is never silently downgraded. It has no effect on Windows or SoftFileLock.

  • preserve_lock_file (bool) – for native locks (FileLock), whether filelock promises not to unlink the lock pathname on release. False (the default) keeps each backend’s cleanup: Windows removes the lock file, Unix already leaves it. True keeps a stable file identity for ACLs, auditing, and holder metadata: Windows skips its post-release unlink and Unix refuses to enter the ENOSYS soft fallback (which releases by unlinking). SoftFileLock rejects True. The promise covers filelock’s own release path only; it cannot stop another process or the filesystem from removing the pathname.

  • on_acquired (Callable[[int], None] | None) – for native locks (FileLock), a callable invoked with the borrowed lock descriptor once per physical acquisition, after filelock holds the native lock and finished backend initialization but before acquire() returns. Recursive acquisitions do not call it again. The callback may read, write, seek, truncate, or set metadata through os on the descriptor, but must not close, unlock, or take ownership of it, and filelock does not fsync its writes. If it raises, filelock releases the lock and re-raises. SoftFileLock rejects the hook.

filelock.lock_descriptor(fd, *, blocking=True, poll_interval=0.05)[source]

Take the native OS lock on fd, a file descriptor the caller opened and owns.

This is the same one-byte exclusive lock FileLock uses, so a descriptor lock and a path lock on the same file contend with each other. Unlike FileLock it adds no path handling: it never opens, truncates, closes, unlinks, chmods, canonicalizes, or falls back. The caller owns fd before, during, and after the call, and must close it. On Windows fd must be a synchronous descriptor (its handle not opened with FILE_FLAG_OVERLAPPED).

For timeout, reentrancy, singleton, lifetime, or stale-break behavior, use FileLock. There is no async wrapper. Run this in an executor, or drive blocking=False from your own polling loop.

Parameters:
  • fd (int) – an open file descriptor the caller owns.

  • blocking (bool) – when True (default), retry the nonblocking attempt every poll_interval seconds until it succeeds; when False, make one attempt.

  • poll_interval (float) – finite, positive seconds between attempts while blocking; ignored when blocking is False.

Return type:

bool

Returns:

True once the lock is held, or False on contention when blocking is False.

Raises:
  • OSError – for a permanent native failure, such as an invalid descriptor, or with errno.ENOSYS when the Python build lacks the native locking primitive. The descriptor is left open.

  • ValueError – if a blocking call receives a non-finite or non-positive poll_interval.

Added in version 3.30.0.

filelock.unlock_descriptor(fd)[source]

Release the native OS lock on fd without touching the descriptor.

Parameters:

fd (int) – the descriptor a prior lock_descriptor() locked; the caller still owns and must close it.

Raises:

OSError – if the native unlock fails, including errno.ENOSYS when the Python build lacks the native locking primitive; the caller may retry on the same descriptor.

Added in version 3.30.0.

Return type:

None