Siren
Minimal Python debug helper with automatic cleanup.
A tiny debugging utility for Python that prints variables with file/line context, traces function calls, measures execution time, and safely removes debug calls from your code.
Install
pip install siren-debug
The package also installs two commands: siren-clean (remove debug calls) and siren-autoload (use siren without importing it).
Quick Start
from siren import siren
x = 10
user = {"name": "Alex", "items": [1, 2, 3]}
siren(x)
siren(user)
[🧜 SIREN core.py:10] x = 10
[🧜 SIREN core.py:11] user = {'name': 'Alex', 'items': [1, 2, 3]}
Siren automatically uses pprint for complex objects, and picks up the file/line it was called from.
Features
- Works with Python 2.7 and 3.6+
- Zero external dependencies
- Prints values with file and line number
- Uses
pprintautomatically for complex data - Function tracing with
@siren.trace, object diffing withsiren.diff, and an interactivesiren.breakpoint() - Quiet mode, conditional logging, and file logging
- Removes
siren(...)calls automatically withsiren-clean - Use
sirenanywhere without importing it viasiren-autoload - Works in scripts, CLI tools, Django, Flask, FastAPI, and more
- Colored output with emoji for easy visual scanning
Usage
Call siren(...) with one or more values. It returns them unchanged, so it can be inlined:
from siren import siren
siren(x, data, user)
result = siren(compute()) # still returns compute()'s value
Label — tag a call for easier scanning:
siren(value, label="BEFORE SAVE")
Timer — measure execution time for a call:
siren(x, timeit=True)
# [🧜 SIREN core.py:10] x = 10
# [🧜 SIREN TIME] 0.000123s
Quiet mode — suppress output without removing the call:
siren(x, quiet=True) # this call only, still returns x
siren.set_quiet(True) # every call, until set_quiet(False)
Conditional logging — only print when a condition holds:
siren(x, if_equals=5) # only if x == 5
siren(items, if_len_gt=100) # only if len(items) > 100
siren(items, if_len_lt=5) # only if len(items) < 5
siren(result, if_true=True) # only if result is truthy
siren(error, if_false=True) # only if error is falsy
Logging to file — mirror output to a file:
siren.set_logfile("debug.log")
siren(x) # prints to stdout AND writes to debug.log
Inspect configuration:
config = siren.get_config()
print(config) # {"quiet": False, "logfile": None, "enabled": True}
Function tracing
@siren.trace logs a function's calls, arguments, return value, execution time, and exceptions automatically:
from siren import trace
@siren.trace
def add(a, b):
return a + b
add(2, 3)
[🧜 SIREN core.py:10] Calling add(a=2, b=3)
[🧜 SIREN core.py:11] Returned from add -> 5 [int] (0.000123s)
Configuration options (all default to True):
| Option | Effect |
|---|---|
timeit |
Show execution time |
show_args |
Show function arguments |
show_return |
Show return value |
show_type |
Show return type in brackets |
@siren.trace(timeit=True, show_args=False, show_type=False)
def multiply(a, b):
return a * b
Exceptions are logged before being re-raised, so @siren.trace never swallows an error:
@siren.trace
def divide(a, b):
return a / b
divide(5, 0) # Logs exception before raising
Diff and breakpoint
siren.diff compares two dicts, lists, tuples, or any comparable objects:
before = {"name": "Alice", "age": 30}
after = {"name": "Alice", "age": 31, "city": "NYC"}
siren.diff(before, after)
[🧜 SIREN test.py:10] DIFF
[🧜 SIREN test.py:11] [~] age: 30 → 31 (changed)
[🧜 SIREN test.py:12] [+] city: NYC (new)
siren.breakpoint() pauses execution and prints local variables:
x = 42
data = {"items": [1, 2, 3]}
siren.breakpoint() # Pauses and displays all locals
# Press Ctrl+C to continue, or type 'd' to drop into pdb
Cleaning debug calls
Run siren-clean in a project folder to remove all siren(...) calls and their import lines — comments and string literals are left untouched:
siren-clean
Before:
from siren import siren
siren(x)
print("hello")
siren(data)
After:
print("hello")
Autoload (no per-file imports)
By default you still need from siren import siren in every file that uses it. If you'd rather call siren(x) anywhere in a project without importing it each time, enable autoload once per environment (virtualenv, Docker image, CI job, etc.):
siren-autoload on
siren-autoload status # check whether it's enabled
siren-autoload off # disable again
This writes a .pth file into the current environment's site-packages, injecting siren into Python's builtins as soon as any interpreter starts in that environment — no import needed anywhere, including in Django apps, Flask views, scripts, or the shell. It's opt-in per environment, so it won't silently affect environments where you didn't run on.
Framework examples
Django
from django.http import JsonResponse
from siren import siren
def my_view(request):
user_data = request.GET.dict()
siren(user_data, label="REQUEST_PARAMS")
result = process_data(user_data)
siren(result)
return JsonResponse(result)
Flask
from flask import Flask, request
from siren import siren, trace
app = Flask(__name__)
@app.route("/api/users")
def get_users():
query = request.args.get("q")
siren(query, label="SEARCH_QUERY")
users = search_users(query)
return {"users": users}
@siren.trace
def search_users(query):
# Function entry/exit will be logged automatically
return [{"id": 1, "name": "Alice"}]
FastAPI
from fastapi import FastAPI
from siren import siren, trace
app = FastAPI()
@app.get("/items/{item_id}")
async def get_item(item_id: int, q: str = None):
siren({"item_id": item_id, "q": q}, label="QUERY_PARAMS")
item = await fetch_item(item_id)
return item
@siren.trace(timeit=True)
async def fetch_item(item_id: int):
# Execution time and arguments will be logged
return {"id": item_id, "name": "Item"}
Why use Siren?
Debug prints are easy to add, but hard to remove later. Siren gives you a fast debug workflow and a safe cleanup step so your temporary debug code does not stay in production.
Project
- Package name:
siren-debug - Python versions:
2.7,3.6+ - License: MIT
- PyPI: https://pypi.org/project/siren-debug/
License
MIT
Release files for siren-debug 0.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 | |
|---|---|---|---|
| siren_debug-0.5.0.tar.gz | 15.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| siren_debug-0.5.0-py2.py3-none-any.whl | Python 3, Python 2 | none | any | Details |
Total release size: 28.5 kB
Release files / siren_debug-0.5.0.tar.gz
| Download URL | siren_debug-0.5.0.tar.gz |
|---|---|
| Size | 15.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
05685e979ff502bf518ecdec792f89d85d2faab213637984cd1ee8da573cf58c
|
|
BLAKE2b-256 checksum How to use checksums |
b6df9ef31598ba3fcec9aae98965b5d0acfaf246ae19a182458469cf25324061
|
| 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 Sep 13, 2026.
Transparency logRelease files / siren_debug-0.5.0-py2.py3-none-any.whl
| Download URL | siren_debug-0.5.0-py2.py3-none-any.whl |
|---|---|
| Size | 12.8 kB |
| Tags | Python 2 Python 3 |
|
SHA-256 checksum How to use checksums |
ad45bb06d78d181935eb262df78721b7b06e7d4798f207bcfc007357d3390c40
|
|
BLAKE2b-256 checksum How to use checksums |
cdc29514a4348cf5ada46af0605a8990347a823406dc2f1aaf3b85ad30dc31b2
|
| 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 Sep 13, 2026.
Transparency log