Horology
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)
| File | Size | Uploaded | |
|---|---|---|---|
| horology-1.5.0.tar.gz | 8.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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