A minimalist Python profiling library with elegant reporting and automatic statistics accumulation
Project description
Gattopy
A minimalist Python profiling library - simple, elegant, and powerful
Gattopy makes it easy to measure the performance of your Python code. With just a decorator or a context manager, you can track execution time and memory usage with clean, human-readable output.
Features
- Simple to use - Just add a decorator or use a context manager
- Time profiling - Accurate execution time measurement
- Memory tracking - Monitor peak and current memory usage
- Clean output - Formatted results with detailed statistics
- Multiple export formats - JSON, CSV, and Markdown reports
- Flexible - Use as decorator or context manager
- Benchmarking tools - Compare and analyze function performance
- Automatic accumulation - Track multiple function calls automatically
- Zero dependencies - Uses only Python standard library
Installation
pip install gattopy
Quick Start
Using the @gatto Decorator
The @gatto decorator is the recommended way to profile functions. It automatically accumulates statistics across multiple calls and provides convenient methods to access results.
from gattopy import gatto
# Basic usage - automatic accumulation
@gatto
def process_data(n):
return sum(range(n))
# Call the function multiple times
process_data(1000)
process_data(5000)
process_data(10000)
# Print accumulated statistics
process_data.print_summary()
# Export results
process_data.export_stats('results.json')
process_data.export_stats('results.csv')
# Get statistics programmatically
stats = process_data.get_stats()
total_calls = process_data.call_count()
@gatto Parameters
silent(bool, default=False): When False, prints execution details for each call. Set to True for batch processing without console output.return_data(bool, default=False): When False, function returns only its result. When True, returns tuple (result, stats).accumulate(bool, default=True): When True, stores all execution statistics in memory for later analysis.show_args(bool, default=True): Display function arguments in output.track_memory(bool, default=True): Track memory usage during execution.
@gatto Methods
Decorated functions gain the following methods:
print_summary(): Print aggregated statistics for all accumulated callsget_stats(): Return list of all accumulated statistics dictionariesget_summary(): Return summary string without printingexport_stats(filepath): Export statistics to JSON, CSV, or Markdown (auto-detected by extension)call_count(): Return number of times function has been calledclear_stats(): Clear all accumulated statistics
Silent Mode Example
@gatto(silent=True)
def compute(x):
return x ** 2
# Run 100 times without console spam
for i in range(100):
compute(i)
# View summary
compute.print_summary()
print(f"Total executions: {compute.call_count()}")
Using Context Managers
Context managers are ideal for profiling code blocks without modifying function definitions.
from gattopy import Profiler, TimeProfiler, MemoryProfiler
# Time profiling
with TimeProfiler("Data Loading") as profiler:
data = load_large_dataset()
print(profiler.result)
# Memory profiling
with MemoryProfiler("Data Processing") as profiler:
processed = process_data(data)
print(profiler.result)
# Combined profiling
with Profiler("Complete Pipeline") as profiler:
result = run_pipeline()
print(f"Took {profiler.elapsed:.2f} seconds")
Context Manager Parameters
Profiler(name, track_memory=True)
name(str): Description of the profiled operationtrack_memory(bool, default=True): Enable memory tracking
TimeProfiler(name)
name(str): Description of the profiled operation
MemoryProfiler(name)
name(str): Description of the profiled operation
Reporting & Exporting
Using Reporter for Manual Collection
The Reporter class allows manual collection and aggregation of profiling results.
from gattopy import Reporter
from gattopy.core import Profiler
reporter = Reporter()
# Collect results from multiple profiled operations
with Profiler("Operation 1") as p1:
result1 = sum(range(100000))
reporter.add_result(p1.result)
with Profiler("Operation 2") as p2:
result2 = [x ** 2 for x in range(50000)]
reporter.add_result(p2.result)
# Print summary
reporter.print_summary()
Export Formats
# Export to JSON
reporter.save_json("profile_results.json")
# Export to CSV
reporter.save_csv("profile_results.csv")
# Export to Markdown
reporter.save_markdown("profile_results.md")
# Or use @gatto's built-in export
@gatto
def my_function():
pass
my_function()
my_function.export_stats('results.json') # Auto-detects format
Benchmarking
Gattopy provides powerful benchmarking tools for performance analysis and function comparison.
benchmark()
Run a function multiple times and collect detailed statistics.
from gattopy import benchmark, format_time
def my_function():
return sum(range(1000))
results = benchmark(
my_function,
iterations=1000,
track_memory=True,
include_iterations=False
)
print(f"Average: {format_time(results['average'])}")
print(f"Median: {format_time(results['median'])}")
print(f"Min: {format_time(results['min'])}")
print(f"Max: {format_time(results['max'])}")
print(f"P95: {format_time(results['p95'])}")
print(f"P99: {format_time(results['p99'])}")
print(f"Std Dev: {format_time(results['std_dev'])}")
if results.get('memory_peak'):
print(f"Peak Memory: {results['memory_peak']:.2f} MB")
benchmark() Parameters
func(callable): Function to benchmarkiterations(int, default=100): Number of times to execute the functiontrack_memory(bool, default=False): Track memory usage during executioninclude_iterations(bool, default=False): Include individual iteration data in results
benchmark() Return Value
Returns a dictionary with:
function_name: Name of the benchmarked functioniterations: Number of iterations executedtimes: List of all execution times (in seconds)average: Mean execution timemedian: Median execution timemin: Minimum execution timemax: Maximum execution timestd_dev: Standard deviationp95: 95th percentilep99: 99th percentilememory_peak: Peak memory usage in MB (if track_memory=True)memory_current: Current memory usage in MB (if track_memory=True)iteration_details: List of per-iteration stats (if include_iterations=True)
compare_functions()
Compare the performance of multiple functions.
from gattopy import compare_functions
def list_comprehension():
return [x ** 2 for x in range(1000)]
def map_function():
return list(map(lambda x: x ** 2, range(1000)))
def generator():
return list(x ** 2 for x in range(1000))
results = compare_functions(
list_comprehension,
map_function,
generator,
iterations=500,
track_memory=True
)
for name, stats in results.items():
print(f"{name}:")
print(f" Average: {format_time(stats['average'])}")
print(f" Memory: {stats.get('memory_peak', 0):.2f} MB")
compare_functions() Parameters
*functions: Variable number of functions to compareiterations(int, default=100): Number of iterations per functiontrack_memory(bool, default=False): Track memory usageinclude_iterations(bool, default=False): Include per-iteration data
compare_functions() Return Value
Returns a dictionary where keys are function names and values are benchmark results (same structure as benchmark()).
Benchmarking Functions with Parameters
Use lambda functions or functools.partial:
from functools import partial
from gattopy import benchmark
def process(data, multiplier):
return [x * multiplier for x in data]
# Using lambda
results = benchmark(lambda: process([1, 2, 3], 10), iterations=1000)
# Using partial
results = benchmark(partial(process, [1, 2, 3], 10), iterations=1000)
Utilities
Formatting Functions
from gattopy import format_time, format_bytes
# Format time (seconds to human-readable)
print(format_time(0.000001)) # "1.00 μs"
print(format_time(0.001)) # "1.00 ms"
print(format_time(1.5)) # "1.50 s"
print(format_time(65)) # "1m 5.0s"
print(format_time(3665)) # "1h 1m 5.0s"
# Format bytes
print(format_bytes(1024)) # "1.00 KB"
print(format_bytes(1048576)) # "1.00 MB"
print(format_bytes(1073741824)) # "1.00 GB"
Aggregation
from gattopy import aggregate_results
# Aggregate multiple ProfileResult objects
results = [result1, result2, result3]
aggregated = aggregate_results(results)
print(f"Average time: {aggregated['time']['average']}")
print(f"Max memory: {aggregated['memory']['max_peak']}")
print(f"Total calls: {aggregated['count']}")
API Reference
Decorators
@gatto()
Primary decorator for function profiling with automatic accumulation.
Parameters:
silent(bool, default=False): Suppress per-call outputreturn_data(bool, default=False): Return (result, stats) tuple instead of just resultaccumulate(bool, default=True): Store statistics for all callsshow_args(bool, default=True): Display function arguments in outputtrack_memory(bool, default=True): Track memory usage
Added Methods:
print_summary(): Print aggregated statisticsget_stats(): Get list of all statistics dictionariesget_summary(): Get summary string without printingexport_stats(filepath): Export to JSON/CSV/Markdowncall_count(): Get number of callsclear_stats(): Clear accumulated data
Context Managers
Profiler(name, track_memory=True)
Profile both time and memory usage.
Parameters:
name(str): Description of the operationtrack_memory(bool, default=True): Enable memory tracking
Attributes:
elapsed: Execution time in secondsresult: ProfileResult object with all data
TimeProfiler(name)
Profile execution time only.
Parameters:
name(str): Description of the operation
Attributes:
elapsed: Execution time in secondsresult: ProfileResult object
MemoryProfiler(name)
Profile memory usage only.
Parameters:
name(str): Description of the operation
Attributes:
result: ProfileResult object with memory data
Functions
benchmark(func, iterations=100, track_memory=False, include_iterations=False)
Benchmark a function with detailed statistics.
Parameters:
func(callable): Function to benchmarkiterations(int, default=100): Number of executionstrack_memory(bool, default=False): Track memory usageinclude_iterations(bool, default=False): Include per-iteration details
Returns: Dictionary with statistical analysis
compare_functions(*functions, iterations=100, track_memory=False, include_iterations=False)
Compare multiple functions.
Parameters:
*functions: Functions to compareiterations(int, default=100): Iterations per functiontrack_memory(bool, default=False): Track memory usageinclude_iterations(bool, default=False): Include per-iteration details
Returns: Dictionary mapping function names to benchmark results
format_time(seconds)
Convert seconds to human-readable format.
Parameters:
seconds(float): Time in seconds
Returns: Formatted string (e.g., "1.50 ms", "2m 30.5s")
format_bytes(bytes)
Convert bytes to human-readable format.
Parameters:
bytes(int): Number of bytes
Returns: Formatted string (e.g., "1.50 MB", "2.30 GB")
aggregate_results(results)
Aggregate multiple ProfileResult objects.
Parameters:
results(list): List of ProfileResult objects
Returns: Dictionary with aggregated statistics
Classes
ProfileResult
Stores profiling results with metadata.
Attributes:
function_name(str): Name of profiled functionexecution_time(float): Execution time in secondsexecution_time_formatted(str): Human-readable timememory_peak(float): Peak memory in MBmemory_current(float): Current memory in MBtimestamp(str): ISO format timestamparguments(dict): Function arguments used
Methods:
to_dict(): Convert to dictionaryto_json(): Convert to JSON string
Reporter
Collect and export multiple profiling results.
Methods:
add_result(result): Add a ProfileResultprint_summary(): Print summary of all resultssave_json(filepath): Export to JSONsave_csv(filepath): Export to CSVsave_markdown(filepath): Export to Markdown
Usage Comparison
When to Use Each Tool
Use @gatto when:
- You want to track a function across multiple calls
- You need automatic accumulation of statistics
- You want built-in export and summary methods
- You're profiling in production code
Use benchmark() when:
- You need statistical analysis (median, percentiles, std dev)
- You want to test a function a specific number of times
- You need per-iteration data for analysis
- You're doing performance testing
Use compare_functions() when:
- You need to compare different implementations
- You want side-by-side performance analysis
- You're optimizing algorithm choice
Use context managers when:
- You need to profile a code block, not a function
- You want one-time profiling
- You're debugging specific sections
Development
Setup Development Environment
# Clone the repository
git clone https://github.com/jeanpoolSM/gattopy.git
cd gattopy
# Quick setup (recommended)
./scripts/setup_dev.sh
# Or manual setup:
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install in development mode
pip install -e ".[dev]"
# Install pre-commit hooks
pre-commit install
Running Tests
# Run all tests
pytest tests/
# Run with coverage
pytest --cov=gattopy tests/
# Run specific test file
pytest tests/test_core.py -v
Code Quality
# Format code
black gattopy/
# Sort imports
isort gattopy/
# Lint code
flake8 gattopy/
# Type checking
mypy gattopy/
Examples
Check the examples/ directory for comprehensive examples:
Basic Examples
gatto_ultra_simple.py- Simple examples using @gatto decoratorgatto_super_simple.py- Advanced decorator configurationgatto_multiple_calls.py- Automatic statistics accumulationbenchmark_examples.py- Benchmarking and comparison examplesdemo_colores.py- Colorized console output demonstration
Advanced Examples
advanced_sorting_analysis.py- Complete sorting algorithm performance analysisapi_monitoring.py- Real-world API performance monitoring simulationgattopy_tutorial.ipynb- Interactive Jupyter notebook tutorial
See examples/README.md for detailed documentation on each example.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
See CHANGELOG.md for a list of changes.
Why "Gattopy"?
Gatto means "cat" in Italian, and cats are known for being quick and efficient - just like this profiling library. The "py" suffix indicates it's for Python.
Made by the Gattopy team
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gattopy-0.1.1.tar.gz.
File metadata
- Download URL: gattopy-0.1.1.tar.gz
- Upload date:
- Size: 32.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab6c1b99a5e1551131a9b016bd155d7f34625c678374c0e9927eee1894fae32f
|
|
| MD5 |
a8e0c93750a46b3ab19f97f555792cfb
|
|
| BLAKE2b-256 |
47a0e055f4baa2c15524772579e2bdb34cb31a4f19d929f687d404e9e97b59ac
|
File details
Details for the file gattopy-0.1.1-py3-none-any.whl.
File metadata
- Download URL: gattopy-0.1.1-py3-none-any.whl
- Upload date:
- Size: 19.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b4b4577fe0982c8f0b19dea09fd49b4a31ba52bae3fe516fb0f1906682341f2
|
|
| MD5 |
8bce5f3c0d1c211926babd23ac3f88fb
|
|
| BLAKE2b-256 |
361c377cb3a3f9ad472b5f689f3dc5d57af5165822e9dc7678d45b7fab07e86d
|