Skip to main content

Tiny dependency-free timing decorator, context manager, and stopwatch utility.

Project description

timerx

Version Python License: MIT Tests Dependencies

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

timerx-0.2.0.tar.gz (16.0 kB view details)

Uploaded Source

Built Distribution

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

timerx-0.2.0-py3-none-any.whl (7.1 kB view details)

Uploaded Python 3

File details

Details for the file timerx-0.2.0.tar.gz.

File metadata

  • Download URL: timerx-0.2.0.tar.gz
  • Upload date:
  • Size: 16.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for timerx-0.2.0.tar.gz
Algorithm Hash digest
SHA256 8da9a21bcbcc6c701629b3f9272986656eba5f63587c90507ce37c8d55f5c143
MD5 e0b2efb4471c093cc029cc5d41bc8b33
BLAKE2b-256 b782379e12ed8ae17d6cfa1393e3e771829303ec249047750bed98d2f0480b15

See more details on using hashes here.

File details

Details for the file timerx-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: timerx-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 7.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for timerx-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d26c6f844bd76c6811ca9cc779be3da841bbbb29a6cb94b33c3d329aa463f4ac
MD5 e599304abd6dc7d24bba6754a1703d57
BLAKE2b-256 e04a0568ceaa58fe66fa738393c25e3e37ab2488101dc18f64a258e63db44b00

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page