{ "info": { "author": "Joshua Tauberer", "author_email": "jt@occams.info", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "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() `__,\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 `__.\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``.", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/JoshData/exclusiveprocess", "keywords": "exclusive process POSIX lock pid concurrent global system", "license": "CC0 (copyright waived)", "maintainer": "", "maintainer_email": "", "name": "exclusiveprocess", "package_url": "https://pypi.org/project/exclusiveprocess/", "platform": "", "project_url": "https://pypi.org/project/exclusiveprocess/", "project_urls": { "Homepage": "https://github.com/JoshData/exclusiveprocess" }, "release_url": "https://pypi.org/project/exclusiveprocess/0.9.4/", "requires_dist": null, "requires_python": "", "summary": "Exclusive process locking to ensure that your code does not execute concurrently, using POSIX file locking.", "version": "0.9.4" }, "last_serial": 2872308, "releases": { "0.9.1": [ { "comment_text": "", "digests": { "md5": "36df8484007332b299999b2dead8f571", "sha256": "088e5880e1a23f07f1357bec29198023f396b64c029eba583b23d7cbc42e69e9" }, "downloads": -1, "filename": "exclusiveprocess-0.9.1.tar.gz", "has_sig": false, "md5_digest": "36df8484007332b299999b2dead8f571", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8577, "upload_time": "2017-01-01T22:03:46", "url": "https://files.pythonhosted.org/packages/8e/63/452d7c8156617b429cf70d25bdf56eeca842653f0316a42cdd7a75b614d6/exclusiveprocess-0.9.1.tar.gz" } ], "0.9.2": [ { "comment_text": "", "digests": { "md5": "c67081b4762e7d156a69644e1ddbbc38", "sha256": "6d0c07aa6d8690484f302ed66fc06045db43a3f53b68dd731d83e2a39d851679" }, "downloads": -1, "filename": "exclusiveprocess-0.9.2.tar.gz", "has_sig": false, "md5_digest": "c67081b4762e7d156a69644e1ddbbc38", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8752, "upload_time": "2017-01-13T19:49:53", "url": "https://files.pythonhosted.org/packages/f9/59/280a65c0c2a90d8f02353e59699fe261baa891c3af36f44b0663c14c0dd6/exclusiveprocess-0.9.2.tar.gz" } ], "0.9.3": [ { "comment_text": "", "digests": { "md5": "9fc7aaa37ad3d51bbd4253ad086005a8", "sha256": "9b659cbb0bd5e8439d3ce05884903185b3e1c21ca0f6aba970ee7d39c0deaa6d" }, "downloads": -1, "filename": "exclusiveprocess-0.9.3.tar.gz", "has_sig": false, "md5_digest": "9fc7aaa37ad3d51bbd4253ad086005a8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8948, "upload_time": "2017-01-15T15:24:17", "url": "https://files.pythonhosted.org/packages/a4/eb/0052b7248bc9b9ea6c101b241ea8c193cf9f7b06018a280b245bc8f2d0c0/exclusiveprocess-0.9.3.tar.gz" } ], "0.9.4": [ { "comment_text": "", "digests": { "md5": "c1b2126a6afed88982c6a4919917a57d", "sha256": "f09c3dda7706e2db9f65b46a3658f5d3a02dbca243e57993c3f9f727f48190a1" }, "downloads": -1, "filename": "exclusiveprocess-0.9.4.tar.gz", "has_sig": false, "md5_digest": "c1b2126a6afed88982c6a4919917a57d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8961, "upload_time": "2017-05-14T00:56:27", "url": "https://files.pythonhosted.org/packages/ff/a3/d142e7a677c4634b9563883981e7e4863a6ec7f282513d29669d10f1ef8a/exclusiveprocess-0.9.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c1b2126a6afed88982c6a4919917a57d", "sha256": "f09c3dda7706e2db9f65b46a3658f5d3a02dbca243e57993c3f9f727f48190a1" }, "downloads": -1, "filename": "exclusiveprocess-0.9.4.tar.gz", "has_sig": false, "md5_digest": "c1b2126a6afed88982c6a4919917a57d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8961, "upload_time": "2017-05-14T00:56:27", "url": "https://files.pythonhosted.org/packages/ff/a3/d142e7a677c4634b9563883981e7e4863a6ec7f282513d29669d10f1ef8a/exclusiveprocess-0.9.4.tar.gz" } ] }