Tiny dependency-free timing decorator, context manager, and stopwatch utility.
Project description
timerx
timerx is a tiny, dependency-free timing utility for Python. It gives you one simple API for timing functions, code blocks, and named stopwatches, then keeps cumulative stats so you can inspect timings programmatically or print a compact summary.
Use it when you want quick timing information without setting up a profiler or
manually calling time.perf_counter() throughout your code.
Features
- Works as a decorator, context manager, or manual stopwatch
- Supports sync and async functions
- Accumulates count, total, average, min, max, and last duration
- Records timings even when decorated functions or context blocks raise
- Supports concurrent named stopwatches
- Provides isolated
TimerX()instances for libraries and tests - Uses only the Python standard library at runtime
Install
pip install timerx
For local development:
pip install -e ".[test]"
pytest
Quick Example
This example shows the three main ways to use timerx: decorate a function, measure a block, and manually start and stop a named timer.
import time
import timerx
@timerx.track
def train_model():
time.sleep(0.2)
train_model()
train_model()
with timerx.lap("preprocessing"):
time.sleep(0.05)
timerx.start("postprocess")
time.sleep(0.01)
elapsed = timerx.stop("postprocess")
print(f"postprocess took {elapsed:.4f}s")
print(timerx.summary())
Example summary:
name count total avg min max last
------------- ----- -------- -------- -------- -------- --------
train_model 2 400ms 200ms 200ms 200ms 200ms
preprocessing 1 50ms 50ms 50ms 50ms 50ms
postprocess 1 10ms 10ms 10ms 10ms 10ms
Timing Functions
Use @timerx.track when you want to measure every call to a function. It works
with or without parentheses. By default, the function name is used as the timing
label, but you can provide a custom name.
@timerx.track
def load_data():
return [1, 2, 3]
@timerx.track()
def preprocess():
return "ready"
@timerx.track(name="model.fit")
def train():
return "done"
Stats accumulate across multiple calls:
load_data()
load_data()
stats = timerx.get_stats()
print(stats["load_data"]["count"]) # 2
print(stats["load_data"]["avg"]) # average duration in seconds
Decorated functions are recorded even if they raise an exception, and the original exception is still raised normally.
Timing Async Functions
track also supports coroutine functions.
@timerx.track(name="fetch")
async def fetch_rows():
return await client.get("/rows")
Timing Code Blocks
Use timerx.lap(name) as a context manager when you want to measure part of a
function. Laps record timings even when the block raises, and nested laps work
naturally.
with timerx.lap("pipeline"):
with timerx.lap("load"):
rows = load_rows()
with timerx.lap("transform"):
rows = transform(rows)
Stopwatches
Use start(name) and stop(name) when the start and end of the work are in
different places. Named stopwatches can run concurrently. If you start the same
name more than once, timerx treats it as a stack, so stop(name) closes the most
recent start.
timerx.start("download")
timerx.start("parse")
timerx.stop("parse")
timerx.stop("download")
stop(name) returns the elapsed duration in seconds and also records it in the
same stats store used by decorators and laps.
Reading Results
Use summary() for human-readable output:
print(timerx.summary())
print(timerx.summary(unit="ms"))
print(timerx.summary(sort_by="total")) # most expensive first
Supported units are auto, s, ms, us, µs, and microseconds. Auto mode
picks seconds, milliseconds, or microseconds per value.
Pass sort_by with any stat column name (count, total, avg, min, max,
last) to sort rows descending by that column. Default is insertion order.
Use get_stats() when you need data for tests, logs, dashboards, or your own
formatting:
stats = timerx.get_stats()
{
"preprocessing": {
"count": 1,
"total": 0.00512,
"min": 0.00512,
"max": 0.00512,
"last": 0.00512,
"avg": 0.00512,
}
}
Durations in get_stats() are always stored as seconds.
Isolated Instances
The top-level timerx.track, timerx.lap, timerx.start, and timerx.stop
helpers share one global timer. For libraries, tests, or applications that need
separate timing state, create a TimerX() instance.
from timerx import TimerX
tx = TimerX()
with tx.lap("local"):
run_work()
print(tx.get_stats())
Resetting
Use reset() to clear recorded timings and running stopwatches.
timerx.reset()
Development
pip install -e ".[test]"
pytest
python examples/demo.py
Contributing
Contributions are welcome. If you find a bug, have an API idea, or want to add coverage for an edge case, please open an issue or pull request.
License
timerx is released under the MIT License. See LICENSE for details.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file timerx-0.4.0.tar.gz.
File metadata
- Download URL: timerx-0.4.0.tar.gz
- Upload date:
- Size: 16.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62c3aa94e499f26c553d59afea3efaf7451887a29b749bba0ab69e32d310507a
|
|
| MD5 |
05bf08367140109449583a48f2e6b774
|
|
| BLAKE2b-256 |
d76638f8fb763e2f49bfb3c7e8151aa77267809215d84183c97b8bd42cb566c4
|
Provenance
The following attestation bundles were made for timerx-0.4.0.tar.gz:
Publisher:
publish.yml on abhijatchaturvedi/timerx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
timerx-0.4.0.tar.gz -
Subject digest:
62c3aa94e499f26c553d59afea3efaf7451887a29b749bba0ab69e32d310507a - Sigstore transparency entry: 1707485617
- Sigstore integration time:
-
Permalink:
abhijatchaturvedi/timerx@e8112594f2c86bf53e6c4c0babc38c1b587d3f43 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/abhijatchaturvedi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e8112594f2c86bf53e6c4c0babc38c1b587d3f43 -
Trigger Event:
release
-
Statement type:
File details
Details for the file timerx-0.4.0-py3-none-any.whl.
File metadata
- Download URL: timerx-0.4.0-py3-none-any.whl
- Upload date:
- Size: 7.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bd14a07dff0d4313e32f860f270fa217dab2f4fe2952083007d03c0857c793ac
|
|
| MD5 |
ac40fc371359c1837d1179ca66e8878c
|
|
| BLAKE2b-256 |
f9682aa0e8164d8e9ebad8fbe137b75116492e00c973fe335cf6a399de168e4b
|
Provenance
The following attestation bundles were made for timerx-0.4.0-py3-none-any.whl:
Publisher:
publish.yml on abhijatchaturvedi/timerx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
timerx-0.4.0-py3-none-any.whl -
Subject digest:
bd14a07dff0d4313e32f860f270fa217dab2f4fe2952083007d03c0857c793ac - Sigstore transparency entry: 1707485621
- Sigstore integration time:
-
Permalink:
abhijatchaturvedi/timerx@e8112594f2c86bf53e6c4c0babc38c1b587d3f43 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/abhijatchaturvedi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e8112594f2c86bf53e6c4c0babc38c1b587d3f43 -
Trigger Event:
release
-
Statement type: