Skip to main content

Horology

PyPI version tests codeql PythonVersion OperatingSystems Downloads License: MIT

Conveniently measures the time of your loops, contexts and functions.

Installation

horology version compatible python
1.5 3.11-3.15
1.4.2 3.10-3.14
1.4.1 3.10-3.13
1.4 3.10-3.12
1.3 3.8-3.11
1.2 3.6-3.9
1.1 3.6-3.8

Horology can be installed with pip. It has no dependencies.

pip install horology

Usage

The following 3 tools will let you measure practically any part of your Python code.

Timing an iterable (list, tuple, generator, etc.)

Quick example

from horology import Timed

animals = ['cat', 'dog', 'crocodile']

for x in Timed(animals):
    feed(x)

Result:

iteration    1: 12 s
iteration    2: 8 s
iteration    3: 100 s

total 3 iterations in 120 s
min/median/max: 8/12/100 s
average (std): 40 (52) s

Customization

You can specify where (if at all) you want each iteration and summary to be printed, e.g.:

for x in Timed(animals, unit='ms',
               iteration_print_fn=logger.debug,
               summary_print_fn=logger.info):
    feed(x)

With sparkline=True, the summary ends with a sparkline of iteration times, e.g. ▄▁▁█▁.

Timing a function with a @timed decorator

Quick example

from horology import timed


@timed
def foo():
    ...

Result:

>>> foo()
foo: 7.12 ms

Customization

Choose time unit and name:

@timed(unit='s', name='Processing took')
def bar():
    ...

Result:

>>> bar()
Processing took 0.185 s

Timing part of code with a Timing context

Quick example

Just wrap your code using a with statement:

from horology import Timing

with Timing(name='Important calculations:'):
    ...

Result:

Important calculations: 12.4 s

Customization

You can suppress default printing and directly use measured time (also within the context):

with Timing(print_fn=None) as t:
    ...

make_use_of(t.interval)

Async code

All three tools work with async code as well:

@timed
async def fetch(url):
    ...

async def main():
    await fetch(url)  # measured until the coroutine finishes

    async with Timing(name='Downloading:'):
        ...

    async for page in Timed(fetch_pages()):
        ...

Failures

If a function decorated with @timed or the code inside Timing raises an exception (also KeyboardInterrupt), the time elapsed is printed with (failed) and also added to the exception, so you can see it right in the traceback, even if printing is turned off:

Traceback (most recent call last):
  ...
TimeoutError: https://example.com
horology: fetch: 1.5 s (failed)

Time units

Time units are by default automatically adjusted, for example you will see foo: 7.12 ms rather than foo: 0.007 s. If you don't like it, you can override this by setting the unit argument with one of these names: ['ns', 'us', 'ms', 's', 'min', 'h', 'd'].

Contributions

Contributions are welcome, see contribution guide.

Internals

Horology internally measures time with perf_counter, which provides the highest available resolution, see docs.

Metadata

Release files for horology 1.5.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 horology 1.5.0
File Size Uploaded
horology-1.5.0.tar.gz 8.4 kB Details

Built distribution (wheel)

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

Total release size: 19.7 kB

Release files / horology-1.5.0.tar.gz

Download URL horology-1.5.0.tar.gz
Size 8.4 kB
Tags Source
SHA-256 checksum
How to use checksums
8ee2d16089f7f21799796f44782472f3482cf38de7bd34dceabe2106c91f13c4
BLAKE2b-256 checksum
How to use checksums
5a544967db9ee079a36f65fa220c8e40b41321c9ed6053240be628f3ec4d71b0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 6, 2026.

Transparency log

Release files / horology-1.5.0-py3-none-any.whl

Download URL horology-1.5.0-py3-none-any.whl
Size 11.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c25ab9c54bbfeb797644b3eb80bb696d365fb90a6ef39c507c472e0ca6057f0f
BLAKE2b-256 checksum
How to use checksums
e5977b089ae2a3704344ac5b29e29c1c58d9ca72884cddd0ac2f9af408596242
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.5.0 This release

2 release files

1.4.2

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

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