corelibs-debug (1.0.0)
Installation
pip install --index-url --extra-index-url https://pypi.org/simple corelibs-debugAbout this package
CoreLibs Debug Support
CoreLibs Python Debug support
This is part of the Python CoreLibs
Overview
A collection of debug support like profiling memory, run timer and to screen status line printing
Install
uv add --index opj-pypi=https://git.egplusww.jp/api/packages/PyPI/pypi/simple/ corelibs-dump-data
Usage
The CoreLibs debug support module contains the following
- corelibs_debug.stack
- corelibs_debug.dump_data
- corelibs_debug.profiling
- corelibs_debug.timer
- corelibs_debug.writeline
corelibs_debug.stack usage
Stack and exception tracing
from corelibs_debug.stack import call_stack, exception_stack
call_stack
print a flat call stack with just method information
def call_stack(
start: int = 0,
skip_last: int = -1,
seperator: str = ' -> ',
reset_start_if_empty: bool = False
) -> str:
- start: start pos, if too high, output will empty until reset_start_if_empty is set
- skip_last: how many on the end to skip, default is the "call_stack" function itself
- seperator: string to separate each entry by, cannot be empty and falls back to ' -> ' if empty
- reset_start_if_empty: if start is set to hight and this is set to True then the start will be set back to 0 and run again
Example:
Below will print a complete call stack in the value error, sample file name is "some_test.py"
from corelibs_debug.stack import call_stack
def some_func(element: str): str
if not element:
raise ValueError(f"Some problem [{call_stack()}]")
return element
def main():
some_func()
if __name__ == "__main__":
main()
Example output for above:
some_test.py:<module>:12 -> some_test.py:main:9 -> some_test.py:some_func:5
exception_stack
Catch stack during an exception thrown, points to the line where the exception was raised
def exception_stack(
exc_stack: OptExcInfo | None = None,
separator: str = ' -> '
) -> str:
- exc_stack: Optional exception stack, if not set sys.exc_info() is used
- seperator: string to separate each entry by, cannot be empty and falls back to ' -> ' if empty
Example:
from corelibs_debug.stack import exception_stack
def __text_exception_test(text: str) -> str:
if not text:
raise ValueError("Call stack returned empty string")
return text
def exception_stack_test():
try:
__text_exception_test("")
except ValueError as e:
exc_stack_str = exception_stack()
print(f"Exception Stack Test: {e}")
print(exc_stack_str)
def main():
exception_stack_test()
if __name__ == "__main__":
main()
Example output for above:
some_test.py:exception_stack_test:9 -> some_test.py:__text_exception_test:5
corelibs_debug.dump_data usage
Formated print of variable values
from corelibs_debug.dump_data import dump_data
dump_data
def dump_data(data: Any, use_indent: bool = True) -> str:
Retuns a formatted string for any data, data will be parsed through json dumps.
Note that bad data might throw some json dump exceptions.
Example
from corelibs_debug.dump_data import dump_data
data = {
"name": "Test",
"value": 123,
"items": [1, 2, 3],
"nested": {"a": 1, "b": 2}
}
print(f"A: {dump_data(data)}")
Example output:
A: {
"name": "Test",
"value": 123,
"items": [
1,
2,
3
],
"nested": {
"a": 1,
"b": 2
}
}
corelibs_debug.profiling usage
from corelibs_debug.profiling import display_top, display_top_str, Profiling
display_top and display_top_str
Prints out the top results for tracemalloc snapshot that was previously collected
def display_top(snapshot: Snapshot, key_type: str = 'lineno', limit: int = 10) -> ProfileData:
def display_top_str(profile_data: ProfileData) -> str:
- snapshot: a tracemalloc.take_snapshot()
- key_type: 'filename', 'lineno' (default), 'traceback'
- limit: how many entries to collect
To run run display top a snapshot has to be collected first.
import tracemalloc
from corelibs_debug.profiling import display_top, display_top_str
tracemalloc.start()
lst: list[Any] = []
for i in range(1000):
lst.append(bytearray(1024 * i)) # Allocate increasing memory
snapshot = tracemalloc.take_snapshot()
tracemalloc.stop()
profile_data = display_top(snapshot, limit=10)
print(display_top_str(profile_data))
Will print
TOP: Top 10 lines
# 1: 499564.3 KiB test-run/some_test.py:7
lst.append(bytearray(1024 * i)) # Allocate increasing memory
# 2: 0.0 KiB test-run/some_test.py:6
for i in range(1000):
Profiling
This uses the psutils to collect memory usage during run
from corelibs_debug.profiling import Profiling
profilig = Profiling()
profiling.start_profiling()
for i in range(1000):
lst.append(bytearray(1024 * i)) # Allocate increasing memory
profiling.end_profiling()
print(profiling.print_profiling())
Will print
Profiling: test_operation RSS: 121.26MB | VMS: 402.65MB | time: 122.46msv
Note that for each start_profiling all previous data is cleared. With get_profiling_data the raw data will be returned.
corelibs_debug.timer usage
from corelibs_debug.timer import Timer
corelibs_debug.writeline usage
from corelibs_debug.writeline import (
write_l,
pr_header,
pr_title,
pr_open,
pr_close,
pr_act
)
Development
UV setup
uv must be installed
Python venv setup
After clone, run the command below to install all dependenciss
uv sync
Build and Publish
uv build
uv publish --index opj-pypi --token <gitea token>
Python tests
All python tests are the tests/ folder. They are structured by the source folder layout
run them with
uv run pytest
Get a coverate report
uv run pytest --cov=<project>
uv run pytest --cov=<project> --cov-report=term-missing
Other tests
In the test-run folder usage and run tests are located, runt them below
uv run test-run/<script>