I want to create a decorator that profiles a method and logs the result. How can this be done?
If you want proper profiling instead of timing, you can use an undocumented feature of cProfile
(from this question):
import cProfile
def profileit(func):
def wrapper(*args, **kwargs):
datafn = func.__name__ + ".profile" # Name the data file sensibly
prof = cProfile.Profile()
retval = prof.runcall(func, *args, **kwargs)
prof.dump_stats(datafn)
return retval
return wrapper
@profileit
def function_you_want_to_profile(...)
...
If you want more control over the file name then you will need another layer of indirection:
import cProfile
def profileit(name):
def inner(func):
def wrapper(*args, **kwargs):
prof = cProfile.Profile()
retval = prof.runcall(func, *args, **kwargs)
# Note use of name from outer scope
prof.dump_stats(name)
return retval
return wrapper
return inner
@profileit("profile_for_func1_001")
def func1(...)
...
It looks complicated, but if you follow it step by step (and note the difference in invoking the profiler) it should become clear.
The decorator would look something like:
import time
import logging
def profile(func):
def wrap(*args, **kwargs):
started_at = time.time()
result = func(*args, **kwargs)
logging.info(time.time() - started_at)
return result
return wrap
@profile
def foo():
pass
Anyway, if you want to do some serious profiling I would suggest you use the profile or cProfile packages.
I like the answer of @detly. But sometimes its a problem to use SnakeViz to view the result.
I made a slightly different version that writes the result as text to the same file:
import cProfile, pstats, io
def profileit(func):
def wrapper(*args, **kwargs):
datafn = func.__name__ + ".profile" # Name the data file sensibly
prof = cProfile.Profile()
retval = prof.runcall(func, *args, **kwargs)
s = io.StringIO()
sortby = 'cumulative'
ps = pstats.Stats(prof, stream=s).sort_stats(sortby)
ps.print_stats()
with open(datafn, 'w') as perf_file:
perf_file.write(s.getvalue())
return retval
return wrapper
@profileit
def function_you_want_to_profile(...)
...
I hope this helps someone...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With