A context manager is an object that defines the runtime context to be established when executing a with statement. The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code.
Let's have a look at below example, suppose I want to calculate the Fibonacci of a number -
def fib_cal(fib_num, memo): if memo[fib_num] is not None: return memo[fib_num] elif fib_num == 1 or fib_num == 2: result = 1 else: result = fib_cal(fib_num-1, memo) + fib_cal(fib_num-2, memo) memo[fib_num] = result return result def get_fibonacci(fib_num): memo = [None] * (fib_num+1) return fib_cal(fib_num, memo) print(fibonacci(100))
- Let suppose if my number if bigger like - 3000
- In the above case, it’ll throw an error-
RecursionError: maximum recursion depth exceeded in comparison
because the maximum recursion limit of the os has been exceeded. you can check recursion limit as follow -
import sys sys.getrecursionlimit()
So, In this kind of situation, we can use context manager which will allow us to allocate and release resources precisely when we want to.
import sys class RecursionLimit: def __init__(self, limit): self.limit = limit self.cur_limit = sys.getrecursionlimit() def __enter__(self): sys.setrecursionlimit(self.limit) def __exit__(self, exc_type, exc_value, exc_traceback): sys.setrecursionlimit(self.cur_limit) MAX_LIMIT = 10000 with RecursionLimit(MAX_LIMIT): print(fibonacci(3000))
__enter__() returns the resource that needs to be managed and the
__exit__() does not return anything but performs the cleanup operations.
Context-managers can be used for other purposes also like- simple file I/O, like opening and closing sockets, implementing set-up and tear-down functionality during testing.
I hope you enjoyed reading this article, If you have any suggestions on your mind, please let me know in the comments.