Skip to main content

varview

A tiny, zero-dependency debug-printing helper for people who check their work, for clean automation.

from varview import debug

count = 42
total = 137
status = "active"

debug(count, total, status)
count = 42

total = 137

status = active

Why this exists

Most debugging habits start the same way: print(f"count: {count}"), scattered through a script, forgotten about, and left in, or worse, silently shaping a result nobody meant to ship.

varview grew out of a data analyst's day-to-day discipline: if you can't see your intermediate values clearly, you can't trust your final ones. The habit it's built for is simple: being able to see every variable in your code, at the point it's actually computed, is what lets you notice when something is wrong, a value that shifted type, a filter that let too much or too little through, a join that didn't do what you expected. Data leakage and other silent corruption is usually invisible not because it's hard to catch, but because nobody was looking at the value when it happened. Making that look cheap and habitual, instead of a special debugging step you only reach for once something already seems broken, is the whole point.

That's the whole philosophy behind this package:

  • See it before you trust it. Print the name and the value, side by side, with no risk of the label drifting out of sync with what it's labeling.
  • Validate loudly, not quietly. Every parameter is checked up front. Bad input fails fast with a clear error instead of producing a confusing result three functions later.
  • Make leakage a choice, not an accident. One global switch silences every debug call in a file at once, so nothing you used to sanity-check an intermediate value can slip into a shared notebook or a production run by accident.

varview doesn't detect leakage, drift, or corruption on its own, it has no idea what your data means. What it does is make the habit that catches those problems, actually looking at your intermediate values, cheap enough to do every time instead of only after something already looks wrong.

Install

pip install varview

Usage

Basic

from varview import debug

count = 42
debug(count)             # unquoted variable -> "count = 42"
debug("Checking count")  # a quoted string prints literally, as-is

Multiple variables, comma-separated

Pass as many variables as you want, separated by commas. No need to wrap them in a list:

count = 42
total = 137
status = "active"

debug(count, total, status)
count = 42

total = 137

status = active

Unquoted variables

You don't have to quote the name at all. varview reads the call's own source code to recover the label, so the variable itself can be passed directly:

debug(count)             # prints "count = 42", no quotes needed
debug(count, total)      # prints both, labels taken straight from source

This is resolved from the source text of the call, not from the runtime type of the value, so it stays correct even if a variable happens to hold a string. region = "north" passed unquoted as debug(region) still prints region = north, exactly like any other variable, it is never confused with the literal-print behavior that quoting triggers (see below).

If the source can't be recovered (for example, calls made from a REPL or from exec()'d code), varview falls back to a best-effort heuristic instead of failing.

Quoted strings print literally

A quoted string isn't looked up anywhere, it's printed exactly as written, the same as a plain print() statement. That makes it a convenient way to drop a header or a note in between the variables you're actually checking:

blended_xg = 1.8
scorelines = ["1-2", "2-0"]

debug("Match stats:", blended_xg, scorelines)
Match stats:

blended_xg = 1.8

scorelines = ['1-2', '2-0']

Quoted vs. unquoted is determined from the call's own source code, not from the runtime type of the value, so this stays correct even when a variable's value happens to be a string.

A variable holding a list or tuple is printed as one value

Each comma-separated argument is always treated as exactly one entry, no matter what its runtime value turns out to be, including when that value is itself a list or tuple:

quarterly_revenue = [120000, 135000, 128000, 151000]
debug(quarterly_revenue)
quarterly_revenue = [120000, 135000, 128000, 151000]

This prints as a single line, the variable is never unpacked into one entry per element. To see multiple entries, pass multiple comma-separated arguments instead:

monthly_churn_rate = 0.034
active_subscribers = 8421
quarterly_revenue = [120000, 135000, 128000, 151000]

debug(monthly_churn_rate, active_subscribers, quarterly_revenue)
monthly_churn_rate = 0.034

active_subscribers = 8421

quarterly_revenue = [120000, 135000, 128000, 151000]

Seeing a value instead of assuming it

The pattern that motivated this package: a quick, visible check right where a value is computed, left in place instead of deleted, and silenced in one line before anything ships.

raw_rows = len(df)
df = df.dropna(subset=["customer_id"])
clean_rows = len(df)
dropped = raw_rows - clean_rows

debug(raw_rows, clean_rows, dropped, color="red")
raw_rows = 10482

clean_rows = 10471

dropped = 11

Seeing dropped here is the difference between knowing exactly what a cleaning step did and just assuming it did what you meant.

Note: older versions of varview used a list-bracket calling convention, debug(["count", "total"]). That form is no longer treated specially, debug([a, b]) is now one argument whose value is a 2-element list, printed as a single line, not unpacked into two. Use plain comma-separated arguments instead: debug(a, b).

Even older versions also looked up quoted strings by name in the caller's local scope (debug("count") would find and print the variable count). That lookup no longer happens. A quoted string is now printed literally, as-is, like a plain print() statement.

Color-code by what the value means to you

debug(count, color="green")   # default, all good
debug(count, color="yellow")  # worth a second look
debug(count, color="red")     # flag it

Color only applies to the label of an unquoted variable's line. A quoted, literal-print line always prints as plain, uncolored text, same as print().

Lay it out the way you're scanning

debug(count, total, status)                              # vertical (default)
debug(count, total, status, orientation="horizontal")     # count = 42, total = 137, status = active

Push a line to the right with pad

pad adds spaces to the left of a line, and it works the same way in either orientation:

debug(count, total, pad=4)      # both lines get 4 leading spaces
    count = 42

    total = 137

Give it a list instead of a single number to control each argument's padding individually. The list has to have exactly one entry per argument passed:

debug(count, total, pad=[2, 6])
  count = 42

      total = 137
debug(count, total, pad=[2])   # only 1 value for 2 arguments
# ValueError: pad list must have exactly 2 value(s) to match the
# 2 argument(s) passed to debug(), got 1

For padding just one argument without spelling out a value for every other one too, wrap that single argument in pad(value, spaces) instead, from the same import:

from varview import debug, pad

debug(pad(count, 4), total)
    count = 42

total = 137

Here count gets 4 leading spaces and total gets none, since it wasn't touched. A pad(...)-wrapped argument's own spacing always wins over the call-level pad= value for that one argument:

debug(pad(count, 4), total, status, pad=1)
    count = 42

 total = 137

 status = active

pad() works on quoted, literal-print lines too, not just variables:

debug(pad("Result:", 2), count)
  Result:

count = 42

Trim the surrounding whitespace

debug(count, total, margin=False)

By default, debug() prints a blank line before and after its output so it stands out in a busy terminal or log. Set margin=False for tightly packed output with nothing extra around it.

Turn one call off without deleting it

debug(count, display=False)

Turn every call off at once, before you share or ship

from varview import debug_off, debug_on

debug_off()   # every debug() call in the process goes silent, even display=True ones
# ... run the rest of your pipeline, notebook export, whatever needs to be clean ...
debug_on()    # back to normal for your next debugging session

debug_off() is the one-line answer to "did I leave a debug print in this notebook before I sent it to someone." Flip it at the top of a cell, or right before a scheduled job runs, and every debug() call downstream goes quiet, no hunting through the file for calls you forgot about.

API

debug(*names, color="green", display=True, orientation="vertical", margin=True, pad=0)

Param Type Default Notes
*names one or more str literals, or unquoted variables, comma-separated (required, at least one) Quoted strings print literally, as-is, no lookup; unquoted variables have their label recovered from source and their value used directly, even if that value is a list or tuple
color "green", "red", "yellow" "green" Label color for unquoted variables only, values always print in black; quoted literal-print lines are always plain, uncolored text
display bool True Silences this one call when False
orientation "vertical", "horizontal" "vertical" Layout of the printed lines
margin bool True Blank line before and after the printed output
pad int or list[int] 0 Spaces added to the left of each line. A single int applies to every line; a list must have exactly one entry per argument passed. Wrap a single argument in pad(value, spaces) (imported alongside debug) to override its padding individually, one argument at a time

All parameters are validated on every call: an invalid color, orientation, or pad raises ValueError or TypeError as appropriate; an invalid display or margin type raises TypeError. Nothing gets a chance to fail silently or print something misleading.

pad(value, spaces)

Wraps a single debug() argument so it can have its own left-padding without affecting any other argument in the same call. Works on both unquoted variables and quoted, literal-print strings. spaces must be a non-negative int.

debug_off() / debug_on()

Module-level switch. debug_off() silences every debug() call in the running process, regardless of that call's own display value. debug_on() restores normal behavior.

License

MIT

Metadata

Release files for varview 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for varview 1.0.1
File Size Uploaded Provenance
varview-1.0.1.tar.gz 15.7 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 34.7 kB

Release files / varview-1.0.1.tar.gz

Download URL varview-1.0.1.tar.gz
Size 15.7 kB
Tags Source
SHA-256 checksum
How to use checksums
585bd7bc0dd98a86f1ef51520c0f75b9f95ba3a75ebedcdeee685253478bc9d3
BLAKE2b-256 checksum
How to use checksums
4206cf68031889b7cd42ad0d6f29454d272dab8b0bc528e3d43d34aabbd4ec5f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.9

Release files / varview-1.0.1-py3-none-any.whl

Download URL varview-1.0.1-py3-none-any.whl
Size 19.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
21cf37278329f925b6513458ed28d0c402d83702a6a5826619c18714b6b00c3a
BLAKE2b-256 checksum
How to use checksums
c69cc5f84fa4fa58bf8385528f511df09907f2cdf14e51f71862748ac6c09de7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.9

Security for varview 1.0.1

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

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