mrkeyoor.com_
Sun 20 Sept 15:54 UTC
PyPIUtilsupdated 20 Sept 2026

toolz review

Toolz 1.1.0 is a pure-Python collection for iterator processing, mapping updates, currying, and function composition. `itertoolz` includes grouping, batching, sliding windows, frequencies, and reductions by key. `dicttoolz` creates updated mappings, while `functoolz` provides `curry`, `pipe`, `compose`, `memoize`, and related call helpers. `toolz.curried` rearranges calls for data-last pipelines, and `tlz` can select cytoolz when available. Version 1.1.0 adds Python 3.14 and PyPy 3.11 support, drops Python 3.8, fixes a `partition_all` edge case, and speeds `merge_sorted`.

Verdict

Toolz 1.1.0 installed in 0.3 seconds as 1 MB with 0 dependencies, and `tlz` imported in 0.14 seconds with 0 pip-audit findings in our sandbox. Keep it where its iterator and mapping vocabulary already pays rent; check the standard library first in new code, and do not expect active feature development or packaged typing.

We installed it

Lab card: what happened when we installed toolzScreenshot of toolz documentation
Install✓ · 0.3s1 package on disk · 1 MB
Importimport tlz in 0.14s · pure Python · requires Python >=3.9
Known vulns0(pip-audit)

Answers from our run

Does toolz install cleanly?

Yes. In a fresh container with an empty cache, pip install toolz finished in 0.3s, leaving 1 package and 1 MB on disk. pip-audit reported no known vulnerabilities.

What does toolz need to run?

Python >=3.9, and nothing compiled: it is pure Python. In our run import tlz succeeded in 0.14s.

toolz or cytoolz: which should you use?

cytoolz: Use it after profiling shows Toolz-compatible transformations are CPU-bound and a compiled wheel is acceptable. Toolz 1.1.0 installed in 0.3 seconds as 1 MB with 0 dependencies, and tlz imported in 0.14 seconds with 0 pip-audit findings in our sandbox.

When should you not use toolz?

You expect new features or quick review of enhancement requests. The README calls Toolz alive but inactive and limits commitment to critical fixes, security, and Python-version updates.

API stability5/5Iterator, mapping, composition, currying, and memoization functions have kept familiar signatures for years, and version 1.1.0 focuses on Python support, packaging, one `partition_all` bug, and `merge_sorted` internals. The project's mostly-complete status makes broad API churn unlikely. Tests are still needed around laziness, exhaustion, and edge inputs because a small behavioral correction can affect pipelines without changing a signature.
Docs4/5Read the Docs separates iterator, dictionary, function, curry, and streaming topics, with an API reference and small executable examples. The README plainly states dependencies, cytoolz compatibility, license location, and inactive project status. Choosing among many similarly named helpers takes some browsing, and the missing `py.typed` marker means editor feedback is weaker than the web signatures suggest.
Maintenance2/5The unarchived repository states that development is inactive and promises attention mainly for critical bugs, security work, and Python-version bumps. Version 1.1.0 shipped on 2025-10-17, the last GitHub push was 2026-01-01, and the combined counter shows 138 open issues and pull requests. That is enough for compatibility upkeep, not a roadmap for requested features.
Ecosystem4/5The package metric records 14,949,137 weekly downloads, and GitHub reports 5,153 stars. Toolz appears directly and through Python data packages, while cytoolz mirrors its API and `tlz` selects between implementations. Integration stays simple because there are no dependencies or plugins. Most ecosystem value comes from an established function vocabulary rather than extensions or framework adapters.

Use it if

  • Existing Python code already expresses grouping, batching, nested mapping updates, or per-key reductions with Toolz vocabulary.
  • A data pipeline benefits from lazy one-pass transformations and curried functions whose collection arrives last.
  • Mapping updates should return new outer structures instead of mutating the original dictionary path.
  • The same imports should use compiled cytoolz when installed and pure Python Toolz as a fallback through `tlz`.
Skip it if

Setup reality

We installed Toolz 1.1.0 in 0.3 seconds in a fresh Python 3.12 container. It left 1 package using 1 MB and has 0 direct dependencies. The distribution is pure Python, requires Python 3.9 or newer, and does not include py.typed. Our measured package metadata did not identify a license, although the project README points to its New BSD license file. pip-audit found 0 known vulnerabilities. import tlz worked in 0.14 seconds.

Import style changes how code reads. toolz exposes ordinary functions, toolz.curried returns functions that can accept arguments across several calls, and tlz chooses cytoolz when present or Toolz otherwise. Curried imports can hide Python built-ins, so a module namespace is easier to audit in mixed code. Supplying too few arguments to a curried function can produce another callable and move the eventual error away from the original call site.

Many iterator helpers are lazy and single-use. take, map, filter, concat, partition, and sliding_window do not return reusable lists. groupby is different because it consumes the source and stores lists in a dictionary. partition drops an incomplete tail unless padding is supplied, while partition_all keeps it. Version 1.1.0 now raises IndexError for an object whose reported length exceeds the items it yields.

Argument order needs checking rather than guessing. groupby(key, seq), valmap(func, mapping), and get_in(keys, mapping) put data last. assoc(mapping, key, value) and update_in(mapping, keys, func) start with the mapping. memoize can grow without a supplied cache policy. In reduceby, a shared mutable initial accumulator can leak state between groups, so prefer an immutable starter or a callable initializer supported by the chosen use.

Patterns

Group records by a field group-records

from toolz import groupby

rows = [
    {'id': 1, 'state': 'open'},
    {'id': 2, 'state': 'closed'},
    {'id': 3, 'state': 'open'},
]

by_state = groupby(lambda row: row['state'], rows)

Toolz consumes the source into a dictionary of lists; unlike `itertools.groupby`, the input need not be sorted.

Count values and derived keys count-groups

from toolz import countby, frequencies

status_counts = countby(lambda row: row['state'], rows)
letter_counts = frequencies('mississippi')

`frequencies` counts items directly, while `countby` computes one key for each item first.

Compose a lazy curried pipeline build-pipeline

from toolz import pipe
from toolz.curried import filter, map, take

result = pipe(
    range(10_000),
    filter(lambda n: n % 7 == 0),
    map(lambda n: n * n),
    take(5),
    list,
)

Curried `map` and `filter` shadow built-ins; evaluation begins at `list`, and `take(5)` limits consumption.

Read a nested path with a default read-nested-value

from toolz import get_in

document = {'user': {'profile': {'visits': 3}}}
visits = get_in(['user', 'profile', 'visits'], document)
email = get_in(['user', 'email'], document, default=None)

`get_in` puts the path before the mapping; a missing path uses the supplied default.

Create a nested mapping update update-nested-value

from toolz import assoc_in, update_in

with_tier = assoc_in(document, ['user', 'profile', 'tier'], 'pro')
with_visit = update_in(
    document, ['user', 'profile', 'visits'], lambda n: n + 1
)

The affected mapping path is copied and the original outer mapping is left unchanged.

Resolve duplicate keys with a function merge-mappings

from toolz import merge_with

totals = merge_with(
    sum,
    {'paper': 4, 'ink': 1},
    {'paper': 3, 'toner': 2},
)

The collision function receives a list of values; plain last-wins merging already exists in dictionary union.

Map and filter dictionary values transform-mapping

from toolz import valfilter, valmap

prices = {'paper': 450, 'ink': 1200, 'toner': 6800}
dollars = valmap(lambda cents: cents / 100, prices)
expensive = valfilter(lambda cents: cents >= 1000, prices)

Both return new mappings; use `itemmap` when the transformation needs each key-value pair.

Keep the last short batch batch-iterator

from toolz import partition_all

for batch in partition_all(500, source_rows):
    write_batch(batch)

`partition_all` yields tuples and preserves the incomplete tail; `partition` drops it unless padding is provided.

Calculate changes between neighbours slide-window

from toolz import sliding_window

changes = (
    current - previous
    for previous, current in sliding_window(2, values)
)

The result is one-pass, and a window larger than the input yields no items.

Aggregate without storing group lists reduce-by-key

from toolz import reduceby

totals = reduceby(
    lambda order: order['customer'],
    lambda total, order: total + order['amount'],
    orders,
    0,
)

`reduceby` retains one accumulator per key; avoid a mutable initializer shared across groups.

Run functions from left to right compose-functions

from toolz import compose_left

slugify = compose_left(
    str.strip,
    str.lower,
    lambda value: value.replace(' ', '-'),
)

slug = slugify('  Open Source Guide  ')

`compose_left` follows reading order, while `compose` starts with the rightmost function.

Import through the backend selector select-backend

from tlz import pipe
from tlz.curried import groupby, map

result = pipe(records, map(normalize), groupby(owner_key))

`tlz` uses cytoolz when installed and otherwise falls back to Toolz; test both if that optional swap is supported.

Alternatives

PackageRegistryPick it when
cytoolzPyPIUse it after profiling shows Toolz-compatible transformations are CPU-bound and a compiled wheel is acceptable.
more-itertoolsPyPIUse it for a wider set of iterator recipes without adopting Toolz's mapping and currying style.
funcyPyPIUse it when Funcy's sequence, collection, and decorator choices fit the team's functional style better.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.