Skip to content

Instantly share code, notes, and snippets.

@benmezger benmezger/debuuger.py
Last active May 10, 2019

Embed
What would you like to do?
import sys
import time
import dis
import cProfile
import pstats
try:
from django.conf import settings
is_django = True
except ImportError:
settings = {}
is_django = False
try:
from ipdb import runcall
except ImportError:
from pdb import runcall
# TODO: Change print to respect logger
# https://stackoverflow.com/questions/10294014/python-decorator-best-practice-using-a-class-vs-a-function
class _Decorator:
def __init__(self, func, logger=None):
self.logger = logger
if not self.logger:
self.logger = logging.getLogger()
self.func = func
self.sys_version = sys.executable
def __call__(self, *args, **kwargs):
raise NotImplemented()
class ObjectInfoDebug(_Decorator):
def __init__(self, func, logger=None):
super().__init__(func, logger)
functools.update_wrapper(self, func)
def __call__(self, *args, **kwargs):
args_repr = (repr(a) for a in args)
kwargs_repr = (f"{k}={v!r}" for k, v in kwargs.items())
signature = ", ".join(list(args_repr) + list(kwargs_repr))
print(f"Calling {self.func.__name__}({signature})")
perf_start = time.perf_counter()
proc_start = time.process_time()
ret = self.func(*args, **kwargs)
total_perf = (time.perf_counter() - perf_start) / 60
total_proc = (time.process_time() - proc_start) / 60
print(f"{self.func.__name__!r} Elapsed time: {total_perf} [min]")
print(f"{self.func.__name__!r} CPU process time: {total_proc} [min]")
print(f"{self.func.__name__!r} returned {ret!r}")
return ret
class PDBDebugger(_Decorator):
def __init__(self, func, logger=None):
super().__init__(func, logger)
functools.update_wrapper(self, func)
def __call__(self, *args, **kwargs):
ret = runcall(self.func, *args, **kwargs)
return ret
class DisassembleDebug(_Decorator):
def __init__(self, func, logger=None):
super().__init__(func, logger)
functools.update_wrapper(self, func)
def __call__(self, *args, **kwargs):
print(dis.dis(self.func))
return self.func(*args, **kwargs)
class ProfilerDebug(_Decorator):
def __init__(self, func, logger=None, profiler_log="profiler.out"):
super().__init__(func, logger)
functools.update_wrapper(self, func)
self.profiler_log = profiler_log
self.prof = cProfile.Profile()
def __call__(self, *args, **kwargs):
self.prof.enable()
try:
ret = self.func(*args, **kwargs)
finally:
self.prof.disable()
with open(self.profiler_log, 'w') as profile_file:
stats = pstats.Stats(self.prof, stream=profile_file)
stats.print_stats()
stats.print_callers()
return ret
@ProfilerDebug(profiler_log="foo.log")
def hello(a, b):
for i in range(10000):
pass
x = 12
return (a, b)
hello(1, 2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.