A Simple Way to Time Code in Python
Read on to find out how to use a decorator to time your functions.
By Edward Krueger, Senior Data Scientist and Tech Lead & Douglas Franklin, Aspiring Data Scientist and Teaching Assistant
Photo by Brad Neathery on Unsplash
Introduction
Our goal is to create an easy way to time functions in Python. We do this by coding a decorator with Python’s libraries functools
 and 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.
We decorate single_threadÂ
with timefuncÂ
using the @Â
symbol.
Now that 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 functools.wraps
.
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
Notice that 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 result
 of func(*args, **kwargs)
 on line 10.
The flexibility of *args
 and **kwargs
allow timefunc
 to work on almost any function. Our closure’s print statement is designed to access the functions __name__
, args
, kwargs
 and result
to create a useful timing output for func
.
Conclusion
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.
Related:
- 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)