Skip to main content

asynctimer

Deterministic, asyncio-native timer for predictable, repeated execution

Overview

asynctimer is a precise, cancellation-safe asyncio timer for Python that avoids drift and enforces fixed scheduling semantics. It is intentionally conservative and explicit, making it suitable for protecting external systems (APIs, databases, hardware) where bursts and ambiguity are unacceptable.

Why this library exists

Many timer utilities:

  • implicitly drift over time
  • allow bursts by default
  • rely on best-effort timing
  • do not clearly specify stop or overrun behavior

asynctimer takes a different approach:

Behavior is explicit, testable, and deterministic — even if that costs some throughput, though in case of timers that's virtually never a concern.


Why not just use asyncio.sleep()?

A common way to implement a repeating task is:

while True:
    await asyncio.sleep(interval)
    do_work()

This approach introduces timer drift because:

  • execution time is added to the interval
  • event loop scheduling latency compounds over time
  • For long-running tasks, this drift becomes observable and problematic.
  • No cancellation mechanism

Installation

pip install asynctimer

What it does

Implements a repeating, async-friendly timer that calls a user-provided callback at a fixed interval until stopped. Callbacks may be synchronous functions or async coroutines.

Timer Guarantees

  • Callbacks never execute concurrently
  • Calling stop() guarantees that no further callbacks will be scheduled or started after it returns.
  • Drift behavior is explicitly configurable
  • Overrun behavior is well-defined and tested

API

  • Timer(timeout: int | float, callback: Callback, schedule_policy: str = "FIXED_SCHEDULE") — create a timer with a repeat interval, callback, and drift policy.
    • timeout_ns: Tick interval in nanoseconds
    • callback: Callable[[], None | Awaitable[None]]
      • May be a synchronous function or an async coroutine
      • Takes no arguments
      • Returns nothing
    • schedule_policy: Drift policy
      • "FIXED_SCHEDULE" (default)
      • "FIXED_DELAY"
    • start() — start the timer loop (non-blocking; schedules repeated executions).
    • stop() — stop the timer loop.

Drift / Schedule Policy

Timers can be scheduled in two fundamentally different ways.

Fixed Schedule (drift-free)

next_tick = initial_start + N × interval
  • Anchored to the original schedule
  • Prevents long-term drift
  • Suitable for:
    • heartbeats
    • simulations
    • clock-aligned tasks
from asynctimer import Timer
# callback can be async too
def callback():
    print('tick')

timer = Timer(
    2000_000_000,
    callback,
    schedule_policy="FIXED_SCHEDULE"
)
timer.start()  # starts the repeating timer
# ... later: timer.stop()

Fixed Delay (completion-relative)

next_tick = callback_completion + interval
  • Guarantees spacing between executions
  • Suitable for:
    • retries
    • polling
    • cooldowns
    • background maintenance
from asynctimer import Timer

timer = Timer(
    2000_000_000,
    callback,
    schedule_policy="FIXED_DELAY"
)
timer.start()

Overrun Behavior

If a callback takes longer than the interval:

  • Missed ticks are not executed retroactively
  • The timer resumes according to its original schedule policy

This avoids burst execution and keeps behavior predictable.

Stop Semantics

Calling stop() guarantees:

  • No further callbacks will be scheduled or started after it returns.

Example

import asyncio
from asynctimer import Timer

# callback can be async too
def callback():
    print('tick')

async def main():
    timer = Timer(2000_000_000, callback)
    timer.start()  # starts the repeating timer
    await asyncio.sleep(10)
    timer.stop()

asyncio.run(main())

Working Examples

For concrete examples showing actual working code using these classes, see the example code in the examples/ directory:


Build Package from Source

The project uses pyproject.toml. To build distribution archives install build and run:

pip install --upgrade build
python -m build

The above produces a dist/ folder with .whl and .tar.gz files. You can also install locally with:

pip install .        # install from source
pip install -e .     # editable install for development

Alternatively, this repository includes build_package.py; you can run it if you prefer (it wraps standard build steps):

python build_package.py

Run Tests

The tests are in the tests/ directory and use unittest's async test support. You can run them with unittest or with pytest.

Run with unittest (cross-platform):

python -m unittest discover -v

Run with pytest (if installed):

pip install pytest
pytest -q

Platform-specific helper scripts are provided:

  • Windows: run_tests.bat
  • Unix/macOS: run_tests.sh

Notes & Troubleshooting

  • The utilities depend only on Python's standard library (asyncio, datetime, etc.). Tests use unittest.IsolatedAsyncioTestCase which requires Python 3.8+.

License

MIT

Metadata

Release files for async-strict-timer 0.1.0

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

Source distribution (sdist)

Source distribution for async-strict-timer 0.1.0
File Size Uploaded Provenance
async_strict_timer-0.1.0.tar.gz 5.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for async-strict-timer 0.1.0
File Interpreter ABI Platform
async_strict_timer-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 10.5 kB

Release files / async_strict_timer-0.1.0.tar.gz

Download URL async_strict_timer-0.1.0.tar.gz
Size 5.1 kB
Tags Source
SHA-256 checksum
How to use checksums
51c75754c63d26e98d00606edf922ba0b4af538d4459d374f8c455e37ed25439
BLAKE2b-256 checksum
How to use checksums
1255ff6c5352b3a0adc70b77cb726ef9b7dc61675df574f06552c57a8745a95a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.2

Release files / async_strict_timer-0.1.0-py3-none-any.whl

Download URL async_strict_timer-0.1.0-py3-none-any.whl
Size 5.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
70b38d34c73621bda33ba429de5328eda5a86cc60f3c31420dbe6489853aa7d3
BLAKE2b-256 checksum
How to use checksums
de86533af9e404511363050dd1ebf2f075488cbb39fd90eea611b1cd6dac2f83
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.2

Security for async-strict-timer 0.1.0

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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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