{"id":861,"library":"fasteners","title":"Fasteners","description":"Fasteners is a Python package that provides useful cross-platform synchronization primitives. It extends Python's standard library by offering inter-process exclusive locks, inter-process reader-writer locks, and thread-based reader-writer locks. The library aims to simplify concurrent programming across processes and threads. The current version is 0.20, with releases occurring periodically, often tied to Python version support updates.","status":"active","version":"0.20","language":"python","source_language":"en","source_url":"https://github.com/harlowja/fasteners","tags":["concurrency","locking","threading","multiprocessing","inter-process"],"install":[{"cmd":"pip install fasteners","lang":"bash","label":"Install latest version"}],"dependencies":[],"imports":[{"symbol":"InterProcessLock","correct":"from fasteners import InterProcessLock"},{"symbol":"InterProcessReaderWriterLock","correct":"from fasteners import InterProcessReaderWriterLock"},{"symbol":"ReaderWriterLock","correct":"from fasteners import ReaderWriterLock"},{"note":"While functional, importing the decorator directly is more explicit for linting and clarity.","wrong":"@fasteners.interprocess_locked","symbol":"interprocess_locked","correct":"from fasteners import interprocess_locked"},{"note":"While functional, importing the decorator directly is more explicit for linting and clarity.","wrong":"@fasteners.locked","symbol":"locked","correct":"from fasteners import locked"}],"quickstart":{"code":"import time\nimport fasteners\nimport os\n\n# For inter-process locks, a file path is required.\n# Use a temporary file path for demonstration.\nlock_file_path = os.path.join(os.getcwd(), 'my_app.lock')\n\n@fasteners.interprocess_locked(lock_file_path)\ndef protected_function(worker_id):\n    print(f\"Worker {worker_id}: Acquired lock. Performing exclusive task...\")\n    time.sleep(2)  # Simulate work\n    print(f\"Worker {worker_id}: Released lock.\")\n\nif __name__ == \"__main__\":\n    print(f\"Attempting to run protected_function for worker 1...\")\n    protected_function(1)\n    print(f\"Attempting to run protected_function for worker 2...\")\n    protected_function(2)\n\n    # Example with context manager for more control\n    print(\"\\n--- Using context manager ---\")\n    my_lock = fasteners.InterProcessLock(lock_file_path + '.ctx')\n    with my_lock:\n        print(\"Main process: Acquired lock via context manager.\")\n        time.sleep(1)\n    print(\"Main process: Released lock via context manager.\")\n    \n    # Clean up lock files (optional, as fasteners typically handles this on exit)\n    if os.path.exists(lock_file_path):\n        os.remove(lock_file_path)\n    if os.path.exists(lock_file_path + '.ctx'):\n        os.remove(lock_file_path + '.ctx')","lang":"python","description":"This quickstart demonstrates using `fasteners.interprocess_locked` as a decorator and `fasteners.InterProcessLock` as a context manager to ensure exclusive execution across processes using a file-based lock. If you run multiple instances of this script simultaneously, only one will execute the protected section at a time."},"warnings":[{"fix":"Ensure your project uses a Python version compatible with your installed `fasteners` version. Refer to the official documentation or release notes for precise compatibility matrix.","message":"Python version support is periodically dropped. Version 0.20 removed support for Python 3.8, 3.9, and PyPy 3.9. Previous versions (0.19, 0.18) also dropped support for older Python releases.","severity":"breaking","affected_versions":"0.18, 0.19, 0.20"},{"fix":"Avoid recursive acquisition of `InterProcessLock`. Design your code so that a process either acquires the lock once or uses alternative reentrant locking mechanisms if recursion is necessary.","message":"`InterProcessLock` instances are *not reentrant*. Attempting to acquire a lock already held by the same process can lead to deadlocks or crashes upon release.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure distinct acquisition patterns. If you need to upgrade a read lock to a write lock (or downgrade), you must explicitly release the first lock before attempting to acquire the second.","message":"`InterProcessReaderWriterLock` instances are *not upgradable*. You cannot acquire a read lock while holding a write lock, or vice versa, without risking deadlocks or crashes.","severity":"gotcha","affected_versions":"All versions"},{"fix":"When using inter-process locks, ensure that any code within the locked section that involves multiple threads in the *same process* is protected by standard Python `threading` locks (e.g., `threading.Lock`) to prevent race conditions.","message":"`InterProcessLock` and `InterProcessReaderWriterLock` provide guarantees *only between processes*, not between threads within a single process. They are not inherently thread-safe for intra-process concurrency.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always use an absolute and consistent file path for your inter-process lock files across all participating processes. Consider using `os.path.join` with a well-known directory or a configuration variable to ensure consistency.","message":"When using `InterProcessLock` or `InterProcessReaderWriterLock`, the `path` argument to the constructor is critical. Different processes must use the exact same string path to refer to the same underlying lock. Mismatched paths will result in independent locks.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"search_vec":"'0.20':58 'across':50 'aim':45 'base':38 'concurr':48,70 'cross':11 'cross-platform':10 'current':55 'exclus':26 'extend':16 'fasten':1,2 'inter':24,29,75 'inter-process':23,28,74 'librari':20,44 'lock':27,34,42,71 'multiprocess':73 'occur':61 'offer':22 'often':63 'packag':6 'period':62 'platform':12 'primit':14 'process':25,30,51,76 'program':49 'provid':8 'python':5,17,66 'reader':32,40 'reader-writ':31,39 'releas':60 'simplifi':47 'standard':19 'support':68 'synchron':13 'thread':37,53,72 'thread-bas':36 'tie':64 'updat':69 'use':9 'version':56,67 'writer':33,41","created_at":"2026-03-29T06:05:09.754612+00:00","updated_at":"2026-04-16T14:57:41.793881+00:00","problems":[{"fix":"Install the package using pip: `pip install fasteners`","cause":"The 'fasteners' package is not installed in the Python environment being used.","error":"ModuleNotFoundError: No module named 'fasteners'"},{"fix":"Instantiate the lock class by adding parentheses: `lock = fasteners.InterProcessLock('path/to/lock.file')` instead of `lock = fasteners.InterProcessLock`","cause":"This error occurs when trying to call the `acquire` method on the `InterProcessLock` or `InterProcessReaderWriterLock` class itself, instead of an instantiated object of that class.","error":"AttributeError: 'builtin_function_or_method' object has no attribute 'acquire'"},{"fix":"Design code to avoid recursive acquisition of `InterProcessLock`. If reentrancy is required, consider using Python's standard library `threading.RLock` for thread-level reentrant locks, or refactor the process-level logic.","cause":"The `fasteners.InterProcessLock` is not reentrant, meaning a process cannot acquire a lock it already holds. Attempting to do so will result in a deadlock or crash.","error":"fasteners InterProcessLock reentrant deadlock"},{"fix":"Explicitly release the first lock (e.g., read lock) before attempting to acquire the second lock (e.g., write lock). Ensure distinct acquisition patterns to prevent concurrent upgrades/downgrades.","cause":"The `fasteners.InterProcessReaderWriterLock` does not support upgrading a read lock to a write lock (or downgrading a write lock to a read lock) while holding the initial lock. This can lead to deadlocks or crashes.","error":"fasteners InterProcessReaderWriterLock upgrade deadlock"},{"fix":"Always check the boolean return value of `acquire(timeout=...)` to determine if the lock was successfully obtained, and handle the case where it returns `False`. Example: `if lock.acquire(timeout=10): ... else: handle_timeout()`","cause":"The `acquire()` method of `InterProcessLock` or `InterProcessReaderWriterLock` returns `False` if the lock cannot be acquired within the specified timeout, rather than raising an exception, which can lead to unexpected behavior if not handled.","error":"fasteners.InterProcessLock acquire timeout"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"0.20","cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/harlowja/fasteners","docs":null,"changelog":null,"pypi":"https://pypi.org/project/fasteners/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["database"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-28","last_verified":"2026-06-28","next_check":"2026-07-28","install_tag":"verified"}}