Skip to main content

simplepyq

Queueing tasks in Python doesn’t have to be complicated.

Overview

simplepyq is a lightweight task queuing library designed for small Python projects that require background task execution without the complexity of heavy tools like Celery, Airflow, or Redis. It uses SQLite for task persistence, ensuring tasks survive application restarts, and provides features like task channels, automatic retries, and dynamic task deferral. With minimal dependencies, simplepyq is easy to set up and ideal for applications needing simple, reliable task queuing.

Features

  • Channels: Organize tasks by associating them with specific functions, enabling grouped task processing.

  • Persistence: Store tasks in a SQLite database to ensure they are not lost during application restarts or crashes.

  • Retries: Automatically retry failed tasks a specified number of times, improving resilience for transient errors.

  • DelayException: Dynamically defer tasks for a specified duration, allowing flexible scheduling based on runtime conditions.

  • Simple Setup: Minimal dependencies and straightforward API, requiring only Python and msgpack.

  • Task Management: Tools to clear failed tasks, requeue them, or remove entire channels, providing control over task lifecycle.

Concepts

Channels

Channels in simplepyq allow you to group tasks by their purpose or associated function. Each channel is linked to a specific Python function that processes tasks, and you can configure the number of worker threads for each channel. This is useful for separating different types of tasks, such as “email” for sending emails and “image_processing” for handling image uploads, ensuring organized and parallel task execution.

Persistence

Tasks are stored in a SQLite database, which provides lightweight persistence without requiring external systems. Each task is saved with its channel, arguments, status (pending, running, delayed, done, or failed), retries, and optional delay timestamp. This ensures tasks are not lost if the application restarts, making simplepyq reliable for long-running operations.

Retries

When a task raises an exception, simplepyq can automatically retry it based on a specified retry count. This is particularly useful for handling transient failures. If retries are exhausted, the task is marked as “failed” for later inspection or requeuing.

DelayException

The DelayException allows tasks to be deferred dynamically by raising an exception with a specified delay in seconds. This is useful for scenarios like rate-limited APIs, where a task needs to wait before retrying, or for scheduling tasks to run at a later time. The task is marked as “delayed” and automatically requeued when the delay period expires.

Task Management

simplepyq provides methods to manage tasks effectively: - clear_failed: Removes failed tasks from the database. - requeue_failed: Requeues failed tasks with their original or a new retry count. - remove_channel: Deletes a channel and all its tasks. - stop and run_until_complete: Control the scheduler’s execution, either running tasks in the background or until all tasks are complete.

Installation

Install simplepyq via pip:

pip install simplepyq

Usage Examples

Below are examples demonstrating each feature of simplepyq, designed to highlight its capabilities in real-world scenarios.

1. Basic Task Queuing with Channels

Organize tasks into a channel for web scraping, processing URLs in the background.

from simplepyq import SimplePyQ

def scrape_url(args):
    url = args["url"]
    print(f"Scraping {url}")

scheduler = SimplePyQ("tasks.db")
scheduler.add_channel("scrape", scrape_url, max_workers=2)  # Two workers for parallel scraping
scheduler.enqueue("scrape", {"url": "https://example.com"})
scheduler.enqueue("scrape", {"url": "https://example.org"})
scheduler.start()  # Runs in the background
# Tasks are processed concurrently by two worker threads

Explanation: The scrape channel is created with a function to process URLs, and two workers allow parallel execution. Tasks are enqueued with arguments and processed asynchronously.

2. Task Retries for Resilience

Handle transient failures, such as network issues, with automatic retries.

from simplepyq import SimplePyQ
import requests

def fetch_data(args):
    url = args["url"]
    response = requests.get(url)
    if response.status_code != 200:
        raise Exception("Failed to fetch data")
    print(f"Fetched data from {url}")

scheduler = SimplePyQ("tasks.db")
scheduler.add_channel("fetch", fetch_data)
scheduler.enqueue("fetch", {"url": "https://api.example.com/data"}, retries=3)  # Retry up to 3 times
scheduler.run_until_complete()  # Runs until all tasks are complete

Explanation: If the API call fails, the task is retried up to three times before being marked as failed, ensuring resilience against temporary issues.

3. Dynamic Task Deferral with DelayException

Defer tasks dynamically, useful for rate-limited APIs.

from simplepyq import SimplePyQ, DelayException

def call_api(args):
    url = args["url"]
    response = requests.get(url)
    if response.status_code == 403:
        raise DelayException(60)  # Wait 60 seconds before retrying
    print(f"Calling {url}")

scheduler = SimplePyQ("tasks.db")
scheduler.add_channel("api", call_api)
scheduler.enqueue("api", {"url": "https://api.example.com/rate_limit"})
scheduler.start()  # Task will be deferred for 60 seconds if rate-limited

Explanation: The DelayException defers the task for 60 seconds, allowing compliance with rate limits or scheduling retries at a later time.

4. Clearing Failed Tasks

Remove failed tasks to clean up the database.

from simplepyq import SimplePyQ

def risky_task(args):
    raise Exception("Task failed intentionally")

scheduler = SimplePyQ("tasks.db")
scheduler.add_channel("risky", risky_task)
scheduler.enqueue("risky", {"data": "test"}, retries=1)
scheduler.run_until_complete()  # Task fails after one retry
scheduler.clear_failed("risky")  # Remove failed tasks for the 'risky' channel

Explanation: After the task fails and retries are exhausted, clear_failed removes it from the database, keeping it clean.

5. Requeuing Failed Tasks

Requeue failed tasks for another attempt.

from simplepyq import SimplePyQ

attempts = 0

def flaky_task(args):
    global attempts
    if attempts < 2:  # Fail on first attempt
        attempts += 1
        raise Exception("Temporary failure")
    print("Task succeeded")

scheduler = SimplePyQ("tasks.db")
scheduler.add_channel("flaky", flaky_task)
scheduler.enqueue("flaky", {}, retries=0)
scheduler.run_until_complete()  # Task fails
scheduler.requeue_failed("flaky", retries=1)  # Requeue with one retry
scheduler.run_until_complete()  # Task succeeds on second attempt

Explanation: Failed tasks are requeued with a new retry count, allowing recovery from temporary issues without manual intervention.

6. Removing a Channel

Delete a channel and its tasks when no longer needed.

from simplepyq import SimplePyQ

def temp_task(args):
    print(f"Processing {args['data']}")

scheduler = SimplePyQ("tasks.db")
scheduler.add_channel("temp", temp_task)
scheduler.enqueue("temp", {"data": "test"})
scheduler.run_until_complete()
scheduler.remove_channel("temp")  # Removes channel and all its tasks

Explanation: The temp channel and its tasks are removed, useful for cleanup when a task type is no longer needed.

7. Running Until Completion

Process all tasks synchronously until complete.

from simplepyq import SimplePyQ

def process_data(args):
    print(f"Processing {args['data']}")

scheduler = SimplePyQ("tasks.db")
scheduler.add_channel("data", process_data)
scheduler.enqueue("data", {"data": "item1"})
scheduler.enqueue("data", {"data": "item2"})
scheduler.run_until_complete()  # Blocks until all tasks are done

Explanation: run_until_complete processes all tasks and stops the scheduler, ideal for scripts or batch processing.

Testing

To run the included unit tests:

python -m unittest discover -s tests

This executes all tests in the tests/ directory, covering task execution, retries, delays, and task management.

License

Licensed under the Apache License 2.0. See the LICENSE file for details.


SimplePyQ is a project powered by The California Open Source Company.

Metadata

Release files for simplepyq 0.1.3

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

Source distribution (sdist)

Source distribution for simplepyq 0.1.3
File Size Uploaded Provenance Actions
simplepyq-0.1.3.tar.gz 11.1 kB With provenance Details for simplepyq-0.1.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for simplepyq 0.1.3
File Interpreter ABI Platform Actions
simplepyq-0.1.3-py3-none-any.whl Python 3 none any Details for simplepyq-0.1.3-py3-none-any.whl

Total release size: 23.5 kB

Release files / simplepyq-0.1.3.tar.gz

Download URL simplepyq-0.1.3.tar.gz
Size 11.1 kB
Tags Source
SHA-256 checksum
How to use checksums
41df2f8c62bae4ead6657a73ea95446d45288cf5e8ee56f905dbde1e02462b76
BLAKE2b-256 checksum
How to use checksums
0269b734ff747a59be68d6dad5e64735d277015e2b2abd4aad09b2e4b5547036
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 12, 2025.

Transparency log

Release files / simplepyq-0.1.3-py3-none-any.whl

Download URL simplepyq-0.1.3-py3-none-any.whl
Size 12.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4c9cfd8ec23b8c6517f8f5ff81c3fcf04c74e98659f03173bdd426adb89377fc
BLAKE2b-256 checksum
How to use checksums
17883ef21e3c0a07cf875f51d3293222cfbeca55c3a307da10d5f3aa5f0bb84e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 12, 2025.

Transparency log

Security for simplepyq 0.1.3

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for simplepyq-0.1.3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 12, 2025.

Transparency log

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