5 real handy python decorators for analyzing/debugging your code
Apply these handy, general-purpose decorators directly to your code
The beauty of decorators is that they are really easy to apply but provide a lot of extra functionalities for your code. In this article we’ll go through 5 handy decorators that you can easily apply to real-world problems you’ll run into when debugging your code. We’ll check out decorators that help you:
- Time your function
- Performance check
- Repeater
- Ask you if you’re sure before executing
- wrap you function in a try-catch
The goal of this article is to offer you some ready-for-use decorators as well as inspire you to come up with some handy, general-purpose decorators.
Before we start: Did you know you can also make decorators keep track of state? Example: count the number of times a function was called so you can rate limit it. Make sure to read this article to understand how decorators work, how to apply them and when to use a decorator. In this article we explore decorators in 6 increasingly more complex steps.
1. Timer
Let’s start easy; we’ll start with a decorator that prints out the time it took for our function to run. This is the code:
Notice that our decorator itself is wrapped with @wraps(func). This is to make sure we pass our wrapped function. If we don’t do this wrapper.__name__
would just print ‘wrapper’ in stead of the function we’re actually decorating.
We’ll use this decorator on a function that calculates primes:
Now we check the output when we call is_prime_number(number=155153)
:[isprime] took 5.601100000000005 ms
2. Performance check
Timing our function is great and all but we want more info. In addition to duration, this next decorator provides information on the function, including the name and docstring, as well as performance information such as memory usage:
It is pretty similar to the previous function, only we print out more information:
Calling is_prime_number(number=9843861881)
will print out the following:Function: is_prime_number ( Checks whether a number is a prime number )
Memory usage: 0.000432 MB
Peak memory usage: 0.000622 MB
Duration: 0.000015 sec
----------------------------------------
3. Repeater
This decorator repeats a certain function when called. This can be convenient for testing performance (see other decorators) or for a stresstest for example
It is used like this:
Calling sayhello() will now produce the following output:hello
hello
This decorator can be nicely used to execute a few times while measuring its performance for example.
4. Prompt “Are you sure?” before executing
This decorator could be added to functions that take a long while to finish or that have significant consequences (like removing data). As soon as you call the function the decorator makes sure that you confirm that you want to execute the function before calling it. Else it will just return and not call the function.
Let’s decorate that simple say_hi function again:
As you see we’re able to set the prompt message on the decorator. When we call say_hi()
this is what you’ll see:Sure? Press y to continue, press n to stop
If you enter a ‘y’ then we’ll execute say_hi()
, any other input (including no input will prevent say_hi()
from executing.
5. TryCatch in a decorator
This wraps your function in a try-except-block using a decorator. The advantage is that with a single line of Python code your whole function is protected against exceptions. This is what the code looks like:
We’ll use this decorator for the function below:
Now, when we call trycatchExample(9, 3)
the fuction returns 3.0
`. If we call trycatchExample(9, 0)
` (dividing by 0) it correctly returns the following:Exception in trycatchExample: division by zero
I’d advise to only use this decorator for debugging purposes and catch errors within the function with more accuracy.
Conclusion
With this article I hope to have provided more information on the advantages that decorators bring. Share some handy decorators of your own if I’ve inspired you! Also, did you know you can even keep state on your decorators? Check out this article for a deep dive into how decorators work.
If you have suggestions/clarifications please comment so I can improve this article. In the meantime, check out my other articles on all kinds of programming-related topics like these:
- Why Python is slow and how to speed it up
- Destroying Duck Hunt with Python OpenCV
- Creating a motion-detector with Python OpenCV
- Advanced multi-tasking in Python: applying and benchmarking threadpools and processpools
- Write you own C extension to speed up Python x100
- Getting started with Cython: how to perform >1.7 billion calculations per second in Python
- Create a fast auto-documented, maintainable and easy-to-use Python API in 5 lines of code with FastAPI
- Create and publish your own Python package
- Create Your Custom, private Python Package That You Can PIP Install From Your Git Repository
- Virtual environments for absolute beginners — what is it and how to create one (+ examples)
- Dramatically improve your database insert speed with a simple upgrade
Happy coding!
— Mike
P.S: like what I’m doing? Follow me!