Python time measure function
First and foremost, I highly suggest using a profiler or atleast use timeit.
However if you wanted to write your own timing method strictly to learn, here is somewhere to get started using a decorator.
Python 2:
def timing(f): def wrap(*args): time1 = time.time() ret = f(*args) time2 = time.time() print '%s function took %0.3f ms' % (f.func_name, (time2-time1)*1000.0) return ret return wrap
And the usage is very simple, just use the @timing decorator:
@timingdef do_work(): #code
Python 3:
def timing(f): def wrap(*args, **kwargs): time1 = time.time() ret = f(*args, **kwargs) time2 = time.time() print('{:s} function took {:.3f} ms'.format(f.__name__, (time2-time1)*1000.0)) return ret return wrap
Note I'm calling f.func_name
to get the function name as a string(in Python 2), or f.__name__
in Python 3.
After playing with the timeit
module, I don't like its interface, which is not so elegant compared to the following two method.
The following code is in Python 3.
The decorator method
This is almost the same with @Mike's method. Here I add kwargs
and functools
wrap to make it better.
def timeit(func): @functools.wraps(func) def new_func(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) elapsed_time = time.time() - start_time print('function [{}] finished in {} ms'.format( func.__name__, int(elapsed_time * 1_000))) return result return new_func@timeitdef foobar(): mike = Person() mike.think(30)
The context manager method
from contextlib import contextmanager@contextmanagerdef timeit_context(name): start_time = time.time() yield elapsed_time = time.time() - start_time print('[{}] finished in {} ms'.format(name, int(elapsed_time * 1_000)))
For example, you can use it like:
with timeit_context('My profiling code'): mike = Person() mike.think()
And the code within the with
block will be timed.
Conclusion
Using the first method, you can easily comment out the decorator to get the normal code. However, it can only time a function. If you have some part of code that you don't what to make it a function, then you can choose the second method.
For example, now you have
images = get_images()big_image = ImagePacker.pack(images, width=4096)drawer.draw(big_image)
Now you want to time the big_image = ...
line. If you change it to a function, it will be:
images = get_images()big_image = None@timeitdef foobar(): nonlocal big_image big_image = ImagePacker.pack(images, width=4096)drawer.draw(big_image)
Looks not so great...What if you are in Python 2, which has no nonlocal
keyword.
Instead, using the second method fits here very well:
images = get_images()with timeit_context('foobar'): big_image = ImagePacker.pack(images, width=4096)drawer.draw(big_image)
I don't see what the problem with the timeit
module is. This is probably the simplest way to do it.
import timeittimeit.timeit(a, number=1)
Its also possible to send arguments to the functions. All you need is to wrap your function up using decorators. More explanation here: http://www.pythoncentral.io/time-a-python-function/
The only case where you might be interested in writing your own timing statements is if you want to run a function only once and are also want to obtain its return value.
The advantage of using the timeit
module is that it lets you repeat the number of executions. This might be necessary because other processes might interfere with your timing accuracy. So, you should run it multiple times and look at the lowest value.