Search code examples
pythonpython-3.xcontextmanager

How do I know which block of code my function is getting called in, in python


I have the following class

class Time:
    def __init__(self) -> None:
        self.time  = 0;
    def __enter__(self):
        self.start = time()
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.end  = time()
        self.time = self.end - self.start
        print(f'The execution of the block took {self.time}s')

and I call it like this

with Time():
    # block 1
    for i in range(100000):
        for ii in range(100):
            pass
    with Time():
        # block 2
        for i in range(1000):
            prime(i)
        with Time():
            # block 3
            ''

This is the output I get:

The execution of the block took 1.6689300537109375e-06s
The execution of the block took 0.0006444454193115234s
The execution of the block took 0.4997687339782715s

which is in the order block 3, 2, 1.

But what if I had a bigger program how will I check which block is calling my function?

I tried to do this:

print(f'The execution of the block {locals()} took {self.time}s')

But that just gives me locals of the class.


Solution

  • You could take a string argument with the label.

    Code:

    class Time:
        def __init__(self, label="") -> None:
            self.time = 0
            self.label = label
    
        def __enter__(self):
            self.start = time()
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.end = time()
            self.time = self.end - self.start
            if not self.label:
                print(f'The execution of the block took {self.time}s')
            else:
                print(f'The execution of the block {self.label} took {self.time}s')
    

    If you want the block names to be 1 through the number of blocks, you can use a class variable, one of the great features of Python.

    Code:

    class Time:
        index = 0
    
        def __init__(self) -> None:
            self.time = 0
            self.index = Time.index
            Time.index += 1
    
        def __enter__(self):
            self.start = time()
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.end = time()
            self.time = self.end - self.start
            print(f'The execution of the block {self.index} took {self.time}s')