Python's missing debug print command and development tools with enhanced debugging, pretty printing, timing, and ANSI styling capabilities.
—
High-precision timing utilities for performance measurement and profiling using Python's perf_counter() for accurate timing. Includes context manager support, multiple timing runs with statistical analysis, and configurable output formatting for development and optimization workflows.
High-precision timer class for measuring code execution time with support for multiple measurements and statistical analysis.
class Timer:
"""
High-precision timer for performance measurement using perf_counter().
"""
def __init__(self, name=None, verbose=True, file=None, dp=3):
"""
Initialize Timer instance.
Parameters:
- name: Optional name for the timer (default: None)
- verbose: Print timing results automatically (default: True)
- file: Output file for timing messages (default: stdout)
- dp: Decimal places for timing display (default: 3)
"""
def __call__(self, name=None, verbose=None) -> Timer:
"""
Update timer configuration and return self for chaining.
Parameters:
- name: Update timer name (optional)
- verbose: Update verbose setting (optional)
Returns:
Self for method chaining
"""
def start(self, name=None, verbose=None) -> Timer:
"""
Start a new timing measurement.
Parameters:
- name: Name for this timing run (overrides instance name)
- verbose: Print result when captured (overrides instance verbose)
Returns:
Self for method chaining
"""
def capture(self, verbose=None) -> TimerResult:
"""
Stop the current timing measurement and optionally print result.
Parameters:
- verbose: Print timing result (overrides instance verbose)
Returns:
TimerResult object containing the timing data
"""
def summary(self, verbose=False) -> list[float]:
"""
Print summary statistics of all timing measurements.
Parameters:
- verbose: Print individual timing results in addition to summary
Returns:
List of elapsed times from all measurements
"""
def __enter__(self) -> Timer:
"""
Context manager entry - starts timing.
Returns:
Self for context manager protocol
"""
def __exit__(self, *args) -> None:
"""
Context manager exit - captures timing result.
Parameters:
- *args: Exception information (ignored)
"""Usage examples:
from devtools import Timer
# Basic timer usage
timer = Timer()
timer.start('operation')
# ... some code to time ...
result = timer.capture()
print(f"Elapsed: {result.elapsed():.3f}s")
# Named timer with context manager
with Timer('database query'):
# ... database operation ...
pass
# Output: database query: 0.123s elapsed
# Multiple timing runs with statistics
timer = Timer('sorting algorithm')
for i in range(10):
timer.start()
# ... sorting operation ...
timer.capture()
times = timer.summary(verbose=True)
# Output: Individual times and summary statistics
# Quiet timer (no automatic printing)
quiet_timer = Timer('background task', verbose=False)
with quiet_timer:
# ... background work ...
pass
result = quiet_timer.results[-1]
print(f"Background task took: {result.elapsed():.2f}s")Represents a single timing measurement with methods for accessing and formatting the timing data.
class TimerResult:
"""
Represents a single timing measurement result.
"""
def __init__(self, name=None, verbose=True):
"""
Initialize TimerResult.
Parameters:
- name: Optional name for this timing result
- verbose: Whether this result should be printed automatically
"""
def capture(self) -> None:
"""
Record the end time for this measurement.
Must be called to finalize the timing result.
"""
def elapsed(self) -> float:
"""
Get the elapsed time in seconds.
Returns:
Elapsed time in seconds, or -1 if not yet captured
"""
def str(self, dp=3) -> str:
"""
Format timing result as string.
Parameters:
- dp: Number of decimal places to display (default: 3)
Returns:
Formatted timing string with name and elapsed time
"""
def __str__(self) -> str:
"""
String representation using default decimal places.
Returns:
Formatted timing string
"""Usage examples:
from devtools import Timer
# Manual timing result handling
timer = Timer(verbose=False)
timer.start('manual timing')
# ... some operation ...
result = timer.capture()
print(f"Operation name: {result._name}")
print(f"Elapsed time: {result.elapsed():.6f}s")
print(f"Formatted: {result.str(dp=6)}")
# Check if timing is complete
if result.elapsed() > 0:
print("Timing completed successfully")Timer supports Python's context manager protocol for convenient timing of code blocks:
from devtools import Timer
# Simple context manager timing
with Timer():
# Code to time
import time
time.sleep(0.1)
# Output: 0.100s elapsed
# Named context manager timing
with Timer('file processing'):
with open('large_file.txt', 'r') as f:
data = f.read()
processed = data.upper()
# Output: file processing: 0.045s elapsed
# Nested timing
with Timer('outer operation'):
# Some setup code
with Timer('inner operation'):
# Critical section
pass
# Some cleanup code
# Output: inner operation: 0.001s elapsed
# outer operation: 0.015s elapsedTimer can collect multiple timing measurements and provide statistical analysis:
from devtools import Timer
# Benchmark a function with multiple runs
def benchmark_function():
# Function to benchmark
return sum(i*i for i in range(1000))
timer = Timer('benchmark')
# Run multiple times
for run in range(100):
timer.start(f'run {run+1}')
result = benchmark_function()
timer.capture(verbose=False) # Don't print individual runs
# Get summary statistics
times = timer.summary()
# Output: 100 times: mean=0.001s stdev=0.000s min=0.001s max=0.002s
print(f"Average time: {sum(times)/len(times):.6f}s")
print(f"Fastest run: {min(times):.6f}s")
print(f"Slowest run: {max(times):.6f}s")Timer integrates seamlessly with the debug system:
from devtools import debug
# Timer created via debug instance
with debug.timer('database operation'):
# Database code here
pass
# Access timer methods through debug
timer = debug.timer('custom timer', verbose=False, dp=6)
with timer:
# Precise timing with 6 decimal places
passThe Timer class uses time.perf_counter() which provides:
import time
from devtools import Timer
# Timing very short operations
with Timer('short operation'):
# Even very fast operations can be timed accurately
x = [i for i in range(100)]
# Output: short operation: 0.000s elapsed (shows microsecond precision)
# Timing longer operations
with Timer('long operation'):
time.sleep(1.0)
# Output: long operation: 1.000s elapsedTimer output can be customized through initialization parameters:
from devtools import Timer
import sys
# Timer with custom output file and precision
with Timer('file operation', dp=6, file=sys.stderr):
with open('test.txt', 'w') as f:
f.write('test data')
# Output to stderr: file operation: 0.001234s elapsed
# Completely silent timer for programmatic use
timer = Timer(verbose=False)
with timer:
# ... operation ...
pass
# Access results programmatically
last_result = timer.results[-1]
if last_result.elapsed() > 0.1:
print("Operation was slow!")# Type alias for string return values
StrType = str
# Timer results storage
results: list[TimerResult] # List of all timing results for a Timer instanceInstall with Tessl CLI
npx tessl i tessl/pypi-devtools