EDIT : Sorry I answered way too fast, and will be editing my answer to incorporate feedback on YOUR code.
Best practice is using lprof
which gives you a line by line timing.
But lprof is a profiler through which you run your calls, rather than a timer you can trigger.
The solution in my current project was to use a class and the with
statement.
This can be called like so :
with Functimer("Expensive Function call"):
foo = expensiveFunction(bar)
and shows up in log as
Starting expensive function call ...
Expensive function call over in 24s
You can use the info
extra parameter to trigger the function timer as a logging.info
rather than logging.debug
(default).
Limitation is it uses directly the logging
module, disregarding the current logger, but that can be worked around
I got the idea from a python recipe, I'll try to find it again. Here's the code
class FuncTimer:
""" Convenience class to time function calls
Use via the "with" keyword ::
with Functimer("Expensive Function call"):
foo = expensiveFunction(bar)
A timer will be displayed in the current logger as `"Starting expensive function call ..."`
then when the code exits the with statement, the log will mention `"Finished expensive function call in 28.42s"`
By default, all FuncTimer log messages are written at the `logging.DEBUG` level. For info-level messages, set the
`FuncTimer.info` argument to `True`::
with Functimer("Expensive Function call",info=True):
foo = expensiveFunction(bar)
"""
def __init__(self, funcName, info=False):
self.funcName = funcName
self.infoLogLevel = info
def __enter__(self):
if self.infoLogLevel:
logging.info("Starting {} ...".format(self.funcName))
else:
logging.debug("Starting {} ...".format(self.funcName))
self.start = time.clock()
return self
def __exit__(self, *args):
self.end = time.clock()
self.interval = self.end - self.start
if self.infoLogLevel:
logging.info("{} over in {}s".format(self.funcName, self.interval).capitalize())
else:
logging.debug("{} over in {}s".format(self.funcName, self.interval).capitalize())