{"id":17247674,"url":"https://github.com/joshdata/exclusiveprocess","last_synced_at":"2025-08-11T19:23:56.748Z","repository":{"id":57427580,"uuid":"77798264","full_name":"JoshData/exclusiveprocess","owner":"JoshData","description":"A simple Python 3 module for ensuring that your code does not execute concurrently in multiple processes, using POSIX file locking.","archived":false,"fork":false,"pushed_at":"2020-06-07T21:45:52.000Z","size":11,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"primary","last_synced_at":"2025-07-29T22:12:47.305Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JoshData.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-01T21:53:47.000Z","updated_at":"2022-12-08T11:58:39.000Z","dependencies_parsed_at":"2022-09-19T06:40:25.410Z","dependency_job_id":null,"html_url":"https://github.com/JoshData/exclusiveprocess","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/JoshData/exclusiveprocess","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoshData%2Fexclusiveprocess","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoshData%2Fexclusiveprocess/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoshData%2Fexclusiveprocess/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoshData%2Fexclusiveprocess/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JoshData","download_url":"https://codeload.github.com/JoshData/exclusiveprocess/tar.gz/refs/heads/primary","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JoshData%2Fexclusiveprocess/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269941623,"owners_count":24500738,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-11T02:00:10.019Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-15T06:38:36.459Z","updated_at":"2025-08-11T19:23:56.702Z","avatar_url":"https://github.com/JoshData.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"exclusiveprocess - Simple Cross-Process Locking in Python\n=========================================================\n\nThis is a simple Python 3.4+ module for ensuring that your code does not\nexecute concurrently in multiple processes, using POSIX file locking.\n\nThe lock can be acquired easily using ``with`` syntax or as a decorator.\n\nWhy?\n----\n\nIf you have long-running processes that would cause corruption if it's\nexecuted multiple times concurrently, this package is for you. You might\nuse this in scripts that make backups, perform database migrations, or\nother long-running processes that need to abort if they are already\nrunning.\n\nHow it works under the hood\n---------------------------\n\nThe module uses POSIX file locking and a PID file:\n\n-  A file is selected to hold lock information, typically\n   ``/var/lock/py_exclusivelock_yournamehere.lock``, called the\n   lockfile, based on a name you provide. The name is sanitized before\n   being used in the filename.\n\n-  If the lockfile already exists and it contains the PID of a running\n   process (including the current process), then a ``CannotAcquireLock``\n   exception is thrown.\n\n-  Otherwise the lockfile is created (or overwritten) and this process's\n   integer process ID is written to the file. POSIX file locking (lockf)\n   and open with O_EXCL is used to prevent race conditions.\n\n-  The lockfile is deleted when the ``with`` block or decorated function\n   exits. Or when used with ``.forever()`` (see below), at program exit.\n\nHow to use it\n-------------\n\nFirst install this package:\n\n::\n\n    pip3 install exclusiveprocess\n\nThen in your Python file import the package:\n\n::\n\n    from exclusiveprocess import Lock, CannotAcquireLock\n\nYou can use it in a ``with`` statement:\n\n::\n\n    try:\n        with Lock(name=\"myprocess\"):\n            print(\"This block cannot be executed concurrently!\")\n    except CannotAcquireLock:\n        print(\"Well, that's bad.\")\n\nOr as a decorator:\n\n::\n\n    # lock name chosen based on __file__\n    @Lock\n    def myfunc():\n        print(\"This function cannot be executed concurrently!\")\n\n    # lock name is \"myprocess\"\n    @Lock(name=\"myprocess\")\n    def myfunc():\n        print(\"This function cannot be executed concurrently!\")\n\nThe ``name`` is up to you. The lock is specific to the name. The name is\nsystem global (as global as the file system is).\n\nThere are also some handy features for locking your whole program.\n\n1. The ``name`` argument is optional and defaults to the filename of the\n   module that contains the function that called ``Lock`` (i.e. your\n   Python source file), using\n   `inspect.stack() \u003chttps://docs.python.org/3.5/library/inspect.html#inspect.stack\u003e`__,\n   which results in the Lock being automatically exclusive to all\n   invocations of your application.\n\n2. When you set the optional ``die`` keyword argument to ``True``,\n   ``Lock`` will print an error to STDERR and exit the process\n   immediately with exit code 1 if the lock cannot be acquired, instead\n   of rasing an exception.\n\n3. The lock can be acquired with ``.forever()``, instead of ``with`` or\n   decorator syntax, in which case the lock will be released only at\n   program exit using\n   `atexit \u003chttps://docs.python.org/3.5/library/atexit.html\u003e`__.\n\nWith these features, you can make your whole program exclusive by\nplacing the following line at the start of your program:\n\n::\n\n    # At program start.\n    Lock(die=True).forever()\n    # program exits here if lock could not be acquired\n\nIf two such programs are run conncurrently you will see on STDERR:\n\n::\n\n    Another '/home/user/your_script.py' process is already running (pid 27922).\n\nAdvanced\n--------\n\nThe ``with`` object can be captured if you want to see where the\nlockfile is stored:\n\n::\n\n    with Lock(name=\"test1\") as lock:\n        print(lock.lockfile)\n\n    # outputs:\n    /var/lock/py_exclusivelock_test1.lock\n\nThe ``Lock`` class logs every lock acquired and released to\n``logging.info``.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshdata%2Fexclusiveprocess","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoshdata%2Fexclusiveprocess","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshdata%2Fexclusiveprocess/lists"}