Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if a function has been called from a loop

Tags:

python

loops

Is it possible to check dynamically whether a function has been called from within a loop?

Example:

def some_function():
    if called_from_loop:
        print("Hey, I'm called from a loop!")

for i in range(0, 1):
    some_function()

some_function()

Expected output:

> Hey, I'm called from a loop!
like image 847
VIPPER Avatar asked Feb 21 '26 21:02

VIPPER


1 Answers

Not sure if this is going to be 100% reliable. It's also rather cumbersome and would have to be written inside the function of interest rather than in its own discrete function for fairly obvious reasons.

We can get the source code for the currently executing .py file

We can also get a stack trace.

Therefore, we can determine the line number in the code from where our function has been called. Thus we can navigate the source code (backwards) taking care to note indentation and see where the indentation decreases and if the line where that occurs starts with either 'for' or 'while' then we were called from within a loop.

So here's the fun:

import traceback
import inspect
import sys

def getws(s):
    return len(s) - len(s.lstrip())

def func():
    source = inspect.getsource(sys.modules[__name__]).splitlines()
    stack = traceback.extract_stack()
    lineno = stack[-2].lineno-1
    isLooped = False
    if (ws := getws(source[lineno])) > 0:
        for i in range(lineno-1, -1, -1):
            if (_ws := getws(line := source[i])) < ws:
                if (tokens := line.split()) and tokens[0] in {'for', 'while'}:
                    isLooped = True
                    break
                if (ws := _ws) == 0:
                    break
    print('Called from loop' if isLooped else 'Not from loop')

def looper():
    for _ in range(1):
        # banana
        func()

def looper2(): # this code is nonsense
    i = 5
    while i > 0:
        if i < 10:
            func()
            break

looper()
looper2()
func()
while True:
    func()
    break
if __name__ == '__main__':
    func()

Output:

Called from loop
Called from loop
Not from loop
Called from loop
Not from loop
like image 194
Ramrab Avatar answered Feb 26 '26 03:02

Ramrab