Skip to main content

yyds-lock

PyPI version License: MIT

中文文档

yyds-lock is an ultra-lightweight, zero-dependency Python library that guarantees single-instance execution of scripts/processes using operating system level advisory file locks. It is ideal for cron jobs, automation scripts, schedulers, and background daemons.

Key Features

  • 🛡️ Immunity to Crashes / Force Kills: Unlike simple PID files or "lock files" that leave stale markers behind if the script crashes, is killed (kill -9), or suffers power loss, yyds-lock binds the lock to the process file descriptor. The OS automatically and instantly releases the lock as soon as the process ends.
  • 🪶 Zero Dependencies: 100% pure Python standard library. The installation size is less than 5KB and does not pollute your environment.
  • 🎛️ Dual Modes: Supports both "Instant Exit" (non-blocking, terminates immediately if another instance is running) and "Queue / Wait" (blocking, waits for the existing instance to finish).
  • 💻 Cross-Platform: Seamlessly works on Linux, macOS (using fcntl.flock), and Windows (using msvcrt.locking).

Installation

pip install -U yyds-lock

Usage

You can protect your script using any of the following approaches:

Pattern A: Direct Call (Best for straightforward scripts / entrypoints)

Place this call at the very top of your entrypoint script. If another instance of the script is already running, the new instance will immediately print an error to stderr and exit with status code 1.

import time
import yyds_lock

# Force single-instance execution.
yyds_lock.force_single(lock_name="my_automation.lock", block=False)

print("Running heavy automation task...")
time.sleep(300)

Pattern B: Decorator (Best for structured functions/main entrypoints)

Decorate your main function to enforce mutual exclusion.

import yyds_lock

@yyds_lock.single_decorator(lock_name="my_task.lock", block=False)
def main():
    print("Executing single instance task safely...")

if __name__ == "__main__":
    main()

Pattern C: Handle Lock Conflict (Exception Raising)

If you prefer to handle the locking failure programmatically (e.g., to perform custom cleanups, log warnings, or run fallback logic) instead of immediately terminating the process, set raise_on_conflict=True to raise AlreadyLockedError:

import yyds_lock
from yyds_lock import AlreadyLockedError

try:
    yyds_lock.force_single(lock_name="my_automation.lock", block=False, raise_on_conflict=True)
except AlreadyLockedError:
    print("Failed to acquire lock. Running fallback script instead...")
    # Add custom fallback actions here

Configuration / Arguments

Both force_single and single_decorator accept the following arguments:

  • lock_name (str): The filename/path of the lock.
    • If a simple filename is given (e.g. "my_job.lock"), it is automatically created in a hidden directory .yyds_lock under the user's home directory (~/.yyds_lock).
    • If an absolute or relative path is given (e.g., "/var/run/my_job.lock"), it is created at that specific path. The parent directories will be created automatically if they do not exist.
  • block (bool):
    • False (default): Exit immediately if the lock cannot be acquired.
    • True: Block and queue, waiting for the active process to finish and release the lock.
  • raise_on_conflict (bool):
    • False (default): Immediately print an error and call sys.exit(1) when the lock is already held.
    • True: Raise AlreadyLockedError when the lock is already held, allowing the caller to catch it.

How It Works Under the Hood

  1. Linux / macOS: Uses fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) for exclusive advisory locking.
  2. Windows: Uses msvcrt.locking(fd, msvcrt.LK_NBLCK, 1) to lock the first byte of the file.
  3. The library stores the open file handles in a global dictionary inside the Python runtime. This keeps the file descriptor open and prevents garbage collection (GC) from releasing the lock prematurely.
  4. When the process terminates (normally, via Exception, sys.exit, crash, kill -9, or power failure), the OS closes the file descriptors, releasing the locks instantly.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yyds_lock-0.2.2.tar.gz (9.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

yyds_lock-0.2.2-py3-none-any.whl (5.9 kB view details)

Uploaded Python 3

File details

Details for the file yyds_lock-0.2.2.tar.gz.

File metadata

  • Download URL: yyds_lock-0.2.2.tar.gz
  • Upload date:
  • Size: 9.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.11

File hashes

Hashes for yyds_lock-0.2.2.tar.gz
Algorithm Hash digest
SHA256 01391f4cb136f322e5ab48a390c8820c5853ea08eeb475e3e8873d78e70845cc
MD5 d8d5d4ae46cbe42a7802d2b668768c39
BLAKE2b-256 74694c201c81eb40cd18b25d839d98e2c2d104c5adbcc43d181965c8f06b01fa

See more details on using hashes here.

File details

Details for the file yyds_lock-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: yyds_lock-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 5.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.11

File hashes

Hashes for yyds_lock-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f43c1720777f4070bbfb631f60c9aa83e464c3a0acb06aa9f95da1067dcb58e2
MD5 4d40ce8eac9c47a2025280226a81517e
BLAKE2b-256 1f35299d094ebfdf120d845ff3f7ace4847b3eb74d88229947ad30381bd6f174

See more details on using hashes here.

Release history Release notifications | RSS feed

0.4.4

2 files

0.4.3

2 files

0.4.2

2 files

0.4.1

2 files

0.4.0

2 files

0.3.0

2 files

0.2.3

2 files

This release

0.2.2 This release

2 files

0.2.1

2 files

0.2.0

2 files

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