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:
- examples/BasicTimerExample.py — basic
Timerusage - examples/MultipleTimersExample.py — using multiple
Timerinstances - examples/SchedulePolicyTimerExample.py — using
SchedulePolicywithTimer
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 useunittest.IsolatedAsyncioTestCasewhich 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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| async_strict_timer-0.1.0.tar.gz | 5.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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.