Skip to content

Instantly share code, notes, and snippets.

@benmezger
Last active May 10, 2019 15:35
Show Gist options
  • Save benmezger/9cdc67a20792c213d2e08888681bf7df to your computer and use it in GitHub Desktop.
Save benmezger/9cdc67a20792c213d2e08888681bf7df to your computer and use it in GitHub Desktop.
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