Skip to main content

A hierarchical, context-manager logger utility with multiprocess mapping capabilities

Project description

logmap

A hierarchical context-manager logger with multiprocess mapping.

Install

pip install logmap

Usage

from logmap import logmap

Basic

with logmap('testing...'):
    # ... do something ...
    pass
⎾ testing... @ 2026-04-19 15:12:55,349
⎿ 0 seconds @ 2026-04-19 15:12:55,349

Duration

with logmap('testing...') as lm:
    naptime = lm.nap()

assert naptime == lm.duration
⎾ testing... @ 2026-04-19 15:12:55,349
│ napping for 0.6 seconds @ 2026-04-19 15:12:55,349
⎿ 0.6 seconds @ 2026-04-19 15:12:55,954

Nested

Nesting indents automatically. lm.log("msg") writes at the current depth.

with logmap('outer') as lm:
    with logmap('middle') as lm2:
        with logmap('inner') as lm3:
            lm3.nap()
⎾ outer @ 2026-04-19 15:12:55,954
│ ⎾ middle @ 2026-04-19 15:12:55,954
│ │ ⎾ inner @ 2026-04-19 15:12:55,954
│ │ │ napping for 0.2 seconds @ 2026-04-19 15:12:55,954
│ │ ⎿ 0.2 seconds @ 2026-04-19 15:12:56,159
│ ⎿ 0.2 seconds @ 2026-04-19 15:12:56,159
⎿ 0.2 seconds @ 2026-04-19 15:12:56,159

Parallel map

import random, time

def fn(naptime):
    t = random.random() * naptime / 2
    time.sleep(t)
    return t

with logmap('function mapping') as lm:
    results = lm.map(fn, list(range(5)), num_proc=2)
⎾ function mapping @ 2026-04-19 15:12:56,159
│ mapping fn to 5 objects [2x]: 100%|██████████| 5/5 [00:02<00:00, 2.31it/s]
⎿ 2.2 seconds @ 2026-04-19 15:12:58,335

For streaming results as they arrive:

with logmap('function mapping') as lm:
    for res in lm.imap(fn, list(range(5)), num_proc=2):
        lm.log(f'got {res:.2f}')   # updates the progress bar

lm.run(...) is the same but discards results — useful when you only care about side effects.

Module-level helpers pmap, pmap_iter, pmap_run provide the same semantics without a logmap context:

from logmap import pmap
pmap(fn, items, num_proc=4)

Note: logmap uses stdlib multiprocessing, so functions passed to parallel map must be picklable (defined at module level — no lambdas or closures).

Without a with block

# just a logger
lm = logmap('app')
lm.log('ready')
lm.warning('careful')

# explicit lifecycle (equivalent to a `with` block)
lm = logmap('manual').start()
lm.log('doing stuff')
lm.stop()

Redirecting output

logmap writes to sys.stderr by default. Use configure() to redirect:

from logmap import configure
import sys

configure(sink=sys.stdout)          # e.g. so it doesn't mingle with stderr diagnostics
configure(sink="run.log")           # path — opened line-buffered
configure(sink=my_stringio)         # any writable stream
configure(level="INFO")             # drop DEBUG messages

Colors auto-disable when the sink isn't a TTY (files, StringIO, etc.).

Stdlib logging integration

Route all logmap output through a standard library logging.Logger:

import logging
from logmap import configure

configure(logger=logging.getLogger("myapp"))

This lets you attach any stdlib handler (file, syslog, etc.) and have logmap participate in your application's logging hierarchy. Level integers match stdlib conventions, so filtering works as expected. Pass logger=None to switch back to direct sink output.

Structured (JSON) output

For log aggregation or machine parsing, enable JSON-lines mode:

configure(structured=True)

Each line becomes a JSON object:

{"ts": "2026-04-19T15:12:55.349000", "level": "INFO", "msg": "doing work", "depth": 1, "task": "outer"}

The msg field contains the clean message (no indentation prefix), while depth and task give you the hierarchical context as structured data.

Silencing

with logmap.quiet():
    with logmap('no output'):       # nothing gets printed
        ...

logmap.disable()                    # global off switch
logmap.enable()                     # back on

with logmap('task', announce=False): suppresses just the open/close lines while keeping lm.log() active.

Thread safety

Nesting depth and quiet state are thread-local — multiple threads can use logmap concurrently without interleaving indentation or silencing each other. Output writes are serialized with a lock to prevent garbled lines.

Multiprocessing on macOS

On macOS, logmap defaults to the forkserver multiprocessing context instead of fork (which Python 3.12+ deprecates due to deadlock risk with threads). You can still pass context="spawn" or context="fork" explicitly to lm.map() / pmap() if needed.

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

logmap-0.3.0.tar.gz (27.0 kB view details)

Uploaded Source

Built Distribution

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

logmap-0.3.0-py3-none-any.whl (21.4 kB view details)

Uploaded Python 3

File details

Details for the file logmap-0.3.0.tar.gz.

File metadata

  • Download URL: logmap-0.3.0.tar.gz
  • Upload date:
  • Size: 27.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for logmap-0.3.0.tar.gz
Algorithm Hash digest
SHA256 0675a522356d62575cf74c6bfca0ee89092924304d4f3d47648499423667c84d
MD5 0f87943adc0f12c06dab7d17b43572a5
BLAKE2b-256 6f2957bdd8908cfc94dd899a8dea52f3e336e356760c9e2b86a2d3b3f4881e2d

See more details on using hashes here.

Provenance

The following attestation bundles were made for logmap-0.3.0.tar.gz:

Publisher: publish.yml on quadrismegistus/logmap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file logmap-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: logmap-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 21.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for logmap-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ce1d9c0b607d2ce281974e2febd491bf1f4ec72feea6d6dbd050d739861d5fc9
MD5 d5889c441dbde87ce4e7f9964542383c
BLAKE2b-256 23a091338b9955596e5540443c2555541efe49e99f7318f5ddd8c379365bf7b7

See more details on using hashes here.

Provenance

The following attestation bundles were made for logmap-0.3.0-py3-none-any.whl:

Publisher: publish.yml on quadrismegistus/logmap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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