Skip to main content

This is a simple Python 3.4+ module for ensuring that your code does not execute concurrently in multiple processes, using POSIX file locking.

The lock can be acquired easily using with syntax or as a decorator.

Why?

If you have long-running processes that would cause corruption if it’s executed multiple times concurrently, this package is for you. You might use this in scripts that make backups, perform database migrations, or other long-running processes that need to abort if they are already running.

How it works under the hood

The module uses POSIX file locking and a PID file:

  • A file is selected to hold lock information, typically /var/lock/py_exclusivelock_yournamehere.lock, called the lockfile, based on a name you provide. The name is sanitized before being used in the filename.

  • If the lockfile already exists and it contains the PID of a running process (including the current process), then a CannotAcquireLock exception is thrown.

  • Otherwise the lockfile is created (or overwritten) and this process’s integer process ID is written to the file. POSIX file locking (lockf) and open with O_EXCL is used to prevent race conditions.

  • The lockfile is deleted when the with block or decorated function exits. Or when used with .forever() (see below), at program exit.

How to use it

First install this package:

pip3 install exclusiveprocess

Then in your Python file import the package:

from exclusiveprocess import Lock, CannotAcquireLock

You can use it in a with statement:

try:
    with Lock(name="myprocess"):
        print("This block cannot be executed concurrently!")
except CannotAcquireLock:
    print("Well, that's bad.")

Or as a decorator:

# lock name chosen based on __file__
@Lock
def myfunc():
    print("This function cannot be executed concurrently!")

# lock name is "myprocess"
@Lock(name="myprocess")
def myfunc():
    print("This function cannot be executed concurrently!")

The name is up to you. The lock is specific to the name. The name is system global (as global as the file system is).

There are also some handy features for locking your whole program.

  1. The name argument is optional and defaults to the filename of the module that contains the function that called Lock (i.e. your Python source file), using inspect.stack(), which results in the Lock being automatically exclusive to all invocations of your application.

  2. When you set the optional die keyword argument to True, Lock will print an error to STDERR and exit the process immediately with exit code 1 if the lock cannot be acquired, instead of rasing an exception.

  3. The lock can be acquired with .forever(), instead of with or decorator syntax, in which case the lock will be released only at program exit using atexit.

With these features, you can make your whole program exclusive by placing the following line at the start of your program:

# At program start.
Lock(die=True).forever()
# program exits here if lock could not be acquired

If two such programs are run conncurrently you will see on STDERR:

Another '/home/user/your_script.py' process is already running (pid 27922).

Advanced

The with object can be captured if you want to see where the lockfile is stored:

with Lock(name="test1") as lock:
    print(lock.lockfile)

# outputs:
/var/lock/py_exclusivelock_test1.lock

The Lock class logs every lock acquired and released to logging.info.

Metadata

Release files for exclusiveprocess 0.9.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for exclusiveprocess 0.9.4
File Size Uploaded Provenance Actions
exclusiveprocess-0.9.4.tar.gz 9.0 kB Without provenance Details for exclusiveprocess-0.9.4.tar.gz

Release files / exclusiveprocess-0.9.4.tar.gz

Download URL exclusiveprocess-0.9.4.tar.gz
Size 9.0 kB
Tags Source
SHA-256 checksum
How to use checksums
f09c3dda7706e2db9f65b46a3658f5d3a02dbca243e57993c3f9f727f48190a1
BLAKE2b-256 checksum
How to use checksums
ffa3d142e7a677c4634b9563883981e7e4863a6ec7f282513d29669d10f1ef8a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Security for exclusiveprocess 0.9.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page