30

I have a function which is called recursively and I want to know the current level of recursion. Below code shows the method that I am using to calculate it, but it is not giving the expected results.

E.g. : To find the recursion level for a system path:

    import os
    funccount = 0

    def reccount(src):
        global funccount
        print "Function level of %s is %d" %(src, funccount)

    def runrec(src):
        global funccount
        funccount = funccount + 1
        lists = os.listdir(src)
        if((len(lists) == 0)):
            funccount = funccount - 1
        reccount(src)
        for x in lists:
             srcname = os.path.join(src, x)
             if((len(lists) - 1) == lists.index(x)):
                  if (not(os.path.isdir(srcname))):
                       funccount = funccount - 1
             if os.path.isdir(srcname):
                runrec(srcname)

    runrec(C:\test)

Problem : Given a directory path, print the level of recursion for directory

Directory Structure is : In my directory structure, i will call the function "reccount(Test)" (Function will be called with path to MainFolder). I want to know the level of recursion call for each folder. (Directory only)

Test:
   |----------doc
   |----------share
                |----------doc
                            |----------file1
   |----------bin
                |----------common
                             |----------doc
   |----------extras
   |----------file2

When i call the procedure, i get the following result:

    Function level of C:\test is 1
    Function level of C:\test\bin is 2
    Function level of C:\test\bin\common is 3
    Function level of C:\test\bin\common\doc is 3
    Function level of C:\test\doc is 3
    Function level of C:\test\extras is 3
    Function level of C:\test\share is 4
    Function level of C:\test\share\doc is 5

As you can see, when it prints results for bin/common/doc, it prints 3 instead of 4 and all subsequent results are wrong

sarbjit
  • 3,786
  • 9
  • 38
  • 60
  • I think the title should be "Specifying a level of recursion in a function". I found this looking for "finding the level of recursion of the function" (without modifying the function). Something like the deep of the stack trace, in order to detect deep calls. – yucer Aug 14 '18 at 12:20
  • The most straightforward / least-effort solution is at https://stackoverflow.com/questions/34115298/how-do-i-get-the-current-depth-of-the-python-interpreter-stack — use `len(inspect.stack(0))` after `import inspect`. (There's also another answer on that question that is faster, but if speed is an issue then manually passing the depth around should be even faster.) – ShreevatsaR Aug 06 '21 at 17:31

3 Answers3

63
def some_method(data, level=0):


    some_method(..., level=level+1)


if __name__ == '__main__':
    some_method(my_data)
34
from inspect import getouterframes, currentframe
import os

def runrec(src):
    level = len(getouterframes(currentframe(1)))
    print("Function level of {} is {}".format(src, level))
    for x in os.listdir(src):
        srcname = os.path.join(src, x)
        if os.path.isdir(srcname):
            runrec(srcname)

runrec('C:\\test')

Function level of C:\test is 1
Function level of C:\test\bin is 2
Function level of C:\test\bin\common is 3
Function level of C:\test\bin\common\doc is 4
Function level of C:\test\doc is 2
Function level of C:\test\extras is 2
Function level of C:\test\share is 2
Function level of C:\test\share\doc is 3
Amper
  • 494
  • 3
  • 3
  • 7
    Although Andreas's answer is the obvious choice for the OP, +1 for a solution that doesn't require the extra parameter. Extremely useful for printing nested debug info from a recursive function without the hassle of the extra param. – Davide Mar 14 '15 at 23:54
  • 2
    if you call this function from another function, the numbers will increase, while recursion depth will remain the same, and parameter based approach lacks this flaw. – Bob Jan 27 '17 at 11:36
  • Just a question.. how is the use of getouterframes and currenteframe different from using inspect.stack() ? – zwep May 30 '18 at 12:36
7

Why don't you store the recursion level in a parameter?

def runrec(src, level=1):
  # ...
  runrec(new_src, level + 1)

That way, you don't need a global variable:

def reccount(src, level):
    print "Function count of {} is {}".format(src, level)
Blender
  • 289,723
  • 53
  • 439
  • 496