Skip to main content

Zero-config line-level Python profiler. Profile any package or script with one command — no @profile decorators, no code changes. Automatic subprocess and multiprocessing support.

Project description

Lazyline

PyPI version Python versions Tests codecov License: MIT

Zero-config, deterministic, line-level Python profiler. No @profile decorators, no code changes — point it at a package or script and go. Subprocesses and multiprocessing pools profiled automatically. Find the lazy lines.

Quick Start

pip install lazyline

# Profile a package while running its tests:
lazyline run my_package -- pytest tests/

# Profile a script:
lazyline run script.py -- python script.py
Discovered 8 module(s) in scope 'my_package'.
Registered 42 function(s) for profiling.

==========================================================================================
  🔥 Lazyline results for my_package
  3 of 42 functions called | Total: 4.1832s | Wall time: 4.0100s | Unit: s (auto)

Summary

Function                                        │Total (s)│ % Total│   Calls│Time/Call (s)
------------------------------------------------------------------------------------------
my_package.cleanup.deduplicate                  │   3.8315│   91.6%│       1│     3.831500
my_package.io.read_csv                          │   0.3412│    8.2%│       1│     0.341200
my_package.cleanup.normalize                    │   0.0105│    0.3%│   10000│     0.000001
------------------------------------------------------------------------------------------
Total                                           │   4.1832

Functions

my_package.cleanup.deduplicate (.../cleanup.py:10)
3.8315s total │ 1 call │ 3.831500s/call

  Line │    Hits │ Time (s) │  Time/Hit (s) │  % Func │Source
------------------------------------------------------------------------------------------
    10 │         │          │               │         │def deduplicate(records):
    11 │       1 │ 0.000100 │      0.000100 │    0.0% │    seen = []
    12 │       1 │ 0.000000 │      0.000000 │    0.0% │    result = []
    13 │   10000 │ 0.003400 │      0.000000 │    0.1% │    for r in records:
    14 │   10000 │ 3.822100 │      0.000382 │   99.8% │        if r not in seen:
    15 │    9813 │ 0.004200 │      0.000000 │    0.1% │            seen.append(r)
    16 │    9813 │ 0.001700 │      0.000000 │    0.0% │            result.append(r)
    17 │       1 │ 0.000000 │      0.000000 │    0.0% │    return result

Line 14 burned 99.8% of deduplicate checking membership in a list on every iteration — that's your lazy line. Change seen to a set and it drops from O(n²) to O(n). Syntax highlighting makes hot lines stand out immediately.

Why Lazyline?

Lazyline wraps line_profiler and adds everything needed to go from "I want to profile this package" to "here are the bottlenecks" in a single command:

  • Zero configuration — point at a package name, directory, or .py file. Every function is discovered and instrumented automatically. No @profile decorators, no code changes — be lazy, let the tool do the work.

  • Subprocess and multiprocessingProcessPoolExecutor, multiprocessing.Pool, and child Python processes (Celery workers, Airflow tasks) are profiled automatically. Results are merged into a single report.

  • Deterministic precision — exact hit counts and timing for every line. "This line ran 47,382 times and took 3.2s." Sampling profilers give statistical approximations; lazyline gives facts. When you need to distinguish O(n) from O(n²), exact counts are the difference.

  • Focused scope, clean output — you choose exactly which package to profile. Unlike tools that profile everything in your working directory, lazyline keeps output relevant and overhead contained.

When to Use What

No tool is best for everything. Pick the right one for the job:

You need... Use Why
Exact line-level timing across a package, no code changes lazyline Deterministic tracing with auto-discovery and subprocess support
Low-overhead profiling with memory, GPU, and AI suggestions Scalene Sampling (~10-20% overhead), broad feature set, web UI
Attach to a running process in production py-spy Out-of-process sampling, near-zero overhead, no restart needed
"Which function is slow?" with beautiful call trees Pyinstrument Statistical profiler, tree output, low overhead
Line-level timing for specific functions you choose kernprof Deterministic, but requires @profile decorators
Quick function-level triage, no install cProfile Stdlib, always available, function-level only

Feature comparison

Feature lazyline kernprof Scalene py-spy Pyinstrument cProfile
Granularity Line Line Line Line Function Function
Method Deterministic Deterministic Sampling Sampling Sampling Deterministic
Code changes needed None @profile None None None None
Exact hit counts Yes Yes No No No Yes (fn-level)
Subprocess profiling Automatic No Partial Yes No No
Multiprocessing pools Automatic No Partial Yes No No
Memory profiling Opt-in No Built-in No No No
GPU profiling No No Yes No No No
Overhead 1.2–7x 1.2–7x ~10–20% ~0% Low Moderate

Lazyline trades overhead for precision. Deterministic tracing fires a callback on every line execution. For functions with real work (>0.1ms per call), overhead is negligible (~1.2x). For tight loops calling tiny functions millions of times, it can reach ~7x. Relative rankings are always reliable — use lazyline to find which code is lazy, not to measure how fast it runs. See benchmarks for detailed measurements.

Usage

# Profile a package during its test suite
lazyline run my_package -- pytest tests/

# Profile while running a script
lazyline run my_package -- python evaluate.py

# Profile a CLI tool (hyphenated console scripts work too)
lazyline run my_package -- my-tool run-all

# Export results, view later
lazyline run -o results.json my_package -- pytest tests/
lazyline show results.json --top 10

# Multiple scopes in one run
lazyline run utils.py my_package -- python script.py

Requires Python 3.10+. The target package must be importable in the same environment.

See the full usage guide for all CLI options, scope formats, command resolution, output details, and more examples.

Documentation


Found a problem with lazyline? Open an issue and tell us about it, or give the project a star if you found it useful.

License

MIT — see LICENSE.

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

lazyline-0.2.0.tar.gz (34.6 kB view details)

Uploaded Source

Built Distribution

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

lazyline-0.2.0-py3-none-any.whl (39.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: lazyline-0.2.0.tar.gz
  • Upload date:
  • Size: 34.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for lazyline-0.2.0.tar.gz
Algorithm Hash digest
SHA256 8e11e7259afd92437f45ddc5544ed60dc977f0e058a1a1ad78568579867588b0
MD5 6e77d3a8437dd8427d0db13f9d570890
BLAKE2b-256 4aa9835cb01bc485bdc3b0ba98a0adcb648be71c825060a7cadf5082ccaa5a4a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: lazyline-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 39.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for lazyline-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 389d835c259cfd897602071b3a5f9f7252ba1b4dc529945c496918443680c906
MD5 75fd986fb06970a300eb3aaaeb645a15
BLAKE2b-256 13de8a9a8dc6bfed38fd545ecf74d5ccee8f5ae3f3837079a77a23e5711061df

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