A Simple Way to Time Code in Python
Read on to find out how to use a decorator to time your functions.
Photo by Brad Neathery on Unsplash
Our goal is to create an easy way to time functions in Python. We do this by coding a decorator with Python’s libraries
time. This decorator will then be applied to functions whose runtime we are interested in.
Timing Decorator: @timefunc
The code below represents a common decorator pattern that has a reusable and flexible structure. Notice the placement of
functool.wraps. It is a decorator for our closure. This decorator preserves
func’s metadata as it is passed to the closure.
Functools becomes significant on line 16, where we access
func.__name__ in our print statement. If we did not use
functools.wraps to decorate our closure, the wrong name would be returned.
This decorator returns the runtime of the function passed to
timefunc(). On line 13,
start initiates timing. Then, line 14's
result stores the value of
func(*args, **kwargs).After that,
time_elapsed is calculated. The print statement reports
func’s name and execution time.
Applying timefunc with the @ symbol
In Python, decorators can be easily applied with the
@ symbol. Not all applications of decorators use this syntax, but all
@ symbols are an application of a decorator.
timefunc using the
single_thread is decorated, when it’s called on line 13 we’ll see its
func.__name__ and runtime.
Output of single_thread decorated by timefunc
If you want to know how this works, below we will go a little deeper into the why and how of coding a decorator to time functions.
Why One Might Time a Function
The reason is relatively straightforward. Faster functions are better functions.
Time is money, friend. — Gazlowe
The timing decorator shows us a function’s runtime. We can apply the decorator to several versions of a function, benchmark them and choose the fastest one. Additionally, it is useful to know how long executions will take when testing code. Got a five-minute runtime ahead? That's a nice window for getting up, moving your legs and refilling your coffee!
To write decorator functions in Python we rely on
functools and an awareness of scope. Let's review scope and decoration.
Decoration, Closures and Scope
Decoration is a design pattern in Python that allows you to modify the behavior of a function. A decorator is a function that takes in a function and returns a modified function.
When writing closures and decorators, you must keep the scope of each function in mind. In Python, functions define scope. Closures have access to the scope of the function that returns them; the decorator’s scope.
It is important to preserve a decorated function's metadata as it is passed to a closure. Knowing our scope lets us properly decorate our closures with
For more on these concepts read this three-minute piece.
Decorators and Closures by Example in Python
How to augment the behavior of a function using a decorator
On the reusability of this decorator
func is taken as an argument on line 7. Then on line 11, we pass
*args, **kwargs, into our closure. These
*args, **kwargs are used to calculate the
func(*args, **kwargs) on line 10.
The flexibility of
timefunc to work on almost any function. Our closure’s print statement is designed to access the functions
resultto create a useful timing output for
Decoration is a powerful tool to augment the behavior of functions. By coding a decorator to time your functions, you gain an elegant, reusable pattern to track a function’s runtime.
Feel free to copy
timefunc into your codebase, or you can try coding your own timing decorator!
Edward Krueger is a Senior Data Scientist and Technical Lead at Business Laboratory and an Instructor at McCombs School of Business at The University of Texas at Austin.
Douglas Franklin is a Teaching Assistant at McCombs School of Business at The University of Texas at Austin.
Original. Reposted with permission.
- 15 common mistakes data scientists make in Python (and how to fix them)
- How to Speed Up Pandas with Modin
- 11 Essential Code Blocks for Complete EDA (Exploratory Data Analysis)